diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/svc/svc_synchronization.cpp | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index 1a8f7e191..9e7bf9530 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp | |||
| @@ -48,19 +48,15 @@ Result ResetSignal(Core::System& system, Handle handle) { | |||
| 48 | return ResultInvalidHandle; | 48 | return ResultInvalidHandle; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 51 | static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles, |
| 52 | Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles, | 52 | int32_t num_handles, int64_t timeout_ns) { |
| 53 | s64 nano_seconds) { | ||
| 54 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}", | ||
| 55 | handles_address, num_handles, nano_seconds); | ||
| 56 | |||
| 57 | // Ensure number of handles is valid. | 53 | // Ensure number of handles is valid. |
| 58 | R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); | 54 | R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); |
| 59 | 55 | ||
| 56 | // Get the synchronization context. | ||
| 60 | auto& kernel = system.Kernel(); | 57 | auto& kernel = system.Kernel(); |
| 58 | auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); | ||
| 61 | std::vector<KSynchronizationObject*> objs(num_handles); | 59 | std::vector<KSynchronizationObject*> objs(num_handles); |
| 62 | const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); | ||
| 63 | Handle* handles = system.Memory().GetPointer<Handle>(handles_address); | ||
| 64 | 60 | ||
| 65 | // Copy user handles. | 61 | // Copy user handles. |
| 66 | if (num_handles > 0) { | 62 | if (num_handles > 0) { |
| @@ -68,21 +64,38 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre | |||
| 68 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, | 64 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, |
| 69 | num_handles), | 65 | num_handles), |
| 70 | ResultInvalidHandle); | 66 | ResultInvalidHandle); |
| 71 | for (const auto& obj : objs) { | ||
| 72 | kernel.RegisterInUseObject(obj); | ||
| 73 | } | ||
| 74 | } | 67 | } |
| 75 | 68 | ||
| 76 | // Ensure handles are closed when we're done. | 69 | // Ensure handles are closed when we're done. |
| 77 | SCOPE_EXIT({ | 70 | SCOPE_EXIT({ |
| 78 | for (s32 i = 0; i < num_handles; ++i) { | 71 | for (auto i = 0; i < num_handles; ++i) { |
| 79 | kernel.UnregisterInUseObject(objs[i]); | ||
| 80 | objs[i]->Close(); | 72 | objs[i]->Close(); |
| 81 | } | 73 | } |
| 82 | }); | 74 | }); |
| 83 | 75 | ||
| 84 | return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()), | 76 | // Wait on the objects. |
| 85 | nano_seconds); | 77 | Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), |
| 78 | static_cast<s32>(objs.size()), timeout_ns); | ||
| 79 | |||
| 80 | R_SUCCEED_IF(res == ResultSessionClosed); | ||
| 81 | R_RETURN(res); | ||
| 82 | } | ||
| 83 | |||
| 84 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | ||
| 85 | Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles, | ||
| 86 | int32_t num_handles, int64_t timeout_ns) { | ||
| 87 | LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles, | ||
| 88 | num_handles, timeout_ns); | ||
| 89 | |||
| 90 | // Ensure number of handles is valid. | ||
| 91 | R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); | ||
| 92 | |||
| 93 | std::vector<Handle> handles(num_handles); | ||
| 94 | if (num_handles > 0) { | ||
| 95 | system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle)); | ||
| 96 | } | ||
| 97 | |||
| 98 | R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns)); | ||
| 86 | } | 99 | } |
| 87 | 100 | ||
| 88 | /// Resumes a thread waiting on WaitSynchronization | 101 | /// Resumes a thread waiting on WaitSynchronization |