summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp37
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp41
3 files changed, 52 insertions, 36 deletions
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index dd662b3f8..d178c2453 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -338,6 +338,15 @@ public:
338 return m_parent != nullptr; 338 return m_parent != nullptr;
339 } 339 }
340 340
341 std::span<KSynchronizationObject*> GetSynchronizationObjectBuffer() {
342 return m_sync_object_buffer.sync_objects;
343 }
344
345 std::span<Handle> GetHandleBuffer() {
346 return {m_sync_object_buffer.handles.data() + Svc::ArgumentHandleCountMax,
347 Svc::ArgumentHandleCountMax};
348 }
349
341 u16 GetUserDisableCount() const; 350 u16 GetUserDisableCount() const;
342 void SetInterruptFlag(); 351 void SetInterruptFlag();
343 void ClearInterruptFlag(); 352 void ClearInterruptFlag();
@@ -855,6 +864,7 @@ private:
855 u32* m_light_ipc_data{}; 864 u32* m_light_ipc_data{};
856 KProcessAddress m_tls_address{}; 865 KProcessAddress m_tls_address{};
857 KLightLock m_activity_pause_lock; 866 KLightLock m_activity_pause_lock;
867 SyncObjectBuffer m_sync_object_buffer{};
858 s64 m_schedule_count{}; 868 s64 m_schedule_count{};
859 s64 m_last_scheduled_tick{}; 869 s64 m_last_scheduled_tick{};
860 std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{}; 870 std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{};
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 60247df2e..bb94f6934 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -38,22 +38,31 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha
38 38
39Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles, 39Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
40 Handle reply_target, s64 timeout_ns) { 40 Handle reply_target, s64 timeout_ns) {
41 // Ensure number of handles is valid.
42 R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
43
44 // Get the synchronization context.
41 auto& kernel = system.Kernel(); 45 auto& kernel = system.Kernel();
42 auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); 46 auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
43 47 auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
44 R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); 48 auto handles = GetCurrentThread(kernel).GetHandleBuffer();
45 R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( 49
46 handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), 50 // Copy user handles.
47 ResultInvalidPointer); 51 if (num_handles > 0) {
48 52 // Ensure we can try to get the handles.
49 std::array<Handle, Svc::ArgumentHandleCountMax> handles; 53 R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
50 GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles); 54 handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
51 55 ResultInvalidPointer);
52 // Convert handle list to object table. 56
53 std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs; 57 // Get the handles.
54 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(), 58 GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
55 num_handles), 59 sizeof(Handle) * num_handles);
56 ResultInvalidHandle); 60
61 // Convert the handles to objects.
62 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
63 objs.data(), handles.data(), num_handles),
64 ResultInvalidHandle);
65 }
57 66
58 // Ensure handles are closed when we're done. 67 // Ensure handles are closed when we're done.
59 SCOPE_EXIT({ 68 SCOPE_EXIT({
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 53df5bcd8..f02d03f30 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -47,21 +47,35 @@ Result ResetSignal(Core::System& system, Handle handle) {
47 R_THROW(ResultInvalidHandle); 47 R_THROW(ResultInvalidHandle);
48} 48}
49 49
50static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles, 50/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
51 int32_t num_handles, int64_t timeout_ns) { 51Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
52 int32_t num_handles, int64_t timeout_ns) {
53 LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
54 num_handles, timeout_ns);
55
52 // Ensure number of handles is valid. 56 // Ensure number of handles is valid.
53 R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); 57 R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
54 58
55 // Get the synchronization context. 59 // Get the synchronization context.
56 auto& kernel = system.Kernel(); 60 auto& kernel = system.Kernel();
57 auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); 61 auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
58 std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs; 62 auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
63 auto handles = GetCurrentThread(kernel).GetHandleBuffer();
59 64
60 // Copy user handles. 65 // Copy user handles.
61 if (num_handles > 0) { 66 if (num_handles > 0) {
67 // Ensure we can try to get the handles.
68 R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
69 user_handles, static_cast<u64>(sizeof(Handle) * num_handles)),
70 ResultInvalidPointer);
71
72 // Get the handles.
73 GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(),
74 sizeof(Handle) * num_handles);
75
62 // Convert the handles to objects. 76 // Convert the handles to objects.
63 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, 77 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
64 num_handles), 78 objs.data(), handles.data(), num_handles),
65 ResultInvalidHandle); 79 ResultInvalidHandle);
66 } 80 }
67 81
@@ -80,23 +94,6 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
80 R_RETURN(res); 94 R_RETURN(res);
81} 95}
82 96
83/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
84Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
85 int32_t num_handles, int64_t timeout_ns) {
86 LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
87 num_handles, timeout_ns);
88
89 // Ensure number of handles is valid.
90 R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
91 std::array<Handle, Svc::ArgumentHandleCountMax> handles;
92 if (num_handles > 0) {
93 GetCurrentMemory(system.Kernel())
94 .ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
95 }
96
97 R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
98}
99
100/// Resumes a thread waiting on WaitSynchronization 97/// Resumes a thread waiting on WaitSynchronization
101Result CancelSynchronization(Core::System& system, Handle handle) { 98Result CancelSynchronization(Core::System& system, Handle handle) {
102 LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); 99 LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);