kernel: Synchronize
This commit is contained in:
		| @@ -338,6 +338,15 @@ public: | |||||||
|         return m_parent != nullptr; |         return m_parent != nullptr; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     std::span<KSynchronizationObject*> GetSynchronizationObjectBuffer() { | ||||||
|  |         return m_sync_object_buffer.sync_objects; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::span<Handle> GetHandleBuffer() { | ||||||
|  |         return {m_sync_object_buffer.handles.data() + Svc::ArgumentHandleCountMax, | ||||||
|  |                 Svc::ArgumentHandleCountMax}; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     u16 GetUserDisableCount() const; |     u16 GetUserDisableCount() const; | ||||||
|     void SetInterruptFlag(); |     void SetInterruptFlag(); | ||||||
|     void ClearInterruptFlag(); |     void ClearInterruptFlag(); | ||||||
| @@ -855,6 +864,7 @@ private: | |||||||
|     u32* m_light_ipc_data{}; |     u32* m_light_ipc_data{}; | ||||||
|     KProcessAddress m_tls_address{}; |     KProcessAddress m_tls_address{}; | ||||||
|     KLightLock m_activity_pause_lock; |     KLightLock m_activity_pause_lock; | ||||||
|  |     SyncObjectBuffer m_sync_object_buffer{}; | ||||||
|     s64 m_schedule_count{}; |     s64 m_schedule_count{}; | ||||||
|     s64 m_last_scheduled_tick{}; |     s64 m_last_scheduled_tick{}; | ||||||
|     std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{}; |     std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{}; | ||||||
|   | |||||||
| @@ -38,22 +38,31 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha | |||||||
|  |  | ||||||
| Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles, | Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles, | ||||||
|                        Handle reply_target, s64 timeout_ns) { |                        Handle reply_target, s64 timeout_ns) { | ||||||
|  |     // Ensure number of handles is valid. | ||||||
|  |     R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); | ||||||
|  |  | ||||||
|  |     // Get the synchronization context. | ||||||
|     auto& kernel = system.Kernel(); |     auto& kernel = system.Kernel(); | ||||||
|     auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); |     auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); | ||||||
|  |     auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); | ||||||
|  |     auto handles = GetCurrentThread(kernel).GetHandleBuffer(); | ||||||
|  |  | ||||||
|     R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); |     // Copy user handles. | ||||||
|     R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( |     if (num_handles > 0) { | ||||||
|                  handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), |         // Ensure we can try to get the handles. | ||||||
|              ResultInvalidPointer); |         R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( | ||||||
|  |                      handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), | ||||||
|  |                  ResultInvalidPointer); | ||||||
|  |  | ||||||
|     std::array<Handle, Svc::ArgumentHandleCountMax> handles; |         // Get the handles. | ||||||
|     GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles); |         GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), | ||||||
|  |                                            sizeof(Handle) * num_handles); | ||||||
|  |  | ||||||
|     // Convert handle list to object table. |         // Convert the handles to objects. | ||||||
|     std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs; |         R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( | ||||||
|     R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(), |                      objs.data(), handles.data(), num_handles), | ||||||
|                                                                      num_handles), |                  ResultInvalidHandle); | ||||||
|              ResultInvalidHandle); |     } | ||||||
|  |  | ||||||
|     // Ensure handles are closed when we're done. |     // Ensure handles are closed when we're done. | ||||||
|     SCOPE_EXIT({ |     SCOPE_EXIT({ | ||||||
|   | |||||||
| @@ -47,21 +47,35 @@ Result ResetSignal(Core::System& system, Handle handle) { | |||||||
|     R_THROW(ResultInvalidHandle); |     R_THROW(ResultInvalidHandle); | ||||||
| } | } | ||||||
|  |  | ||||||
| static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles, | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | ||||||
|                                   int32_t num_handles, int64_t timeout_ns) { | Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles, | ||||||
|  |                            int32_t num_handles, int64_t timeout_ns) { | ||||||
|  |     LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles, | ||||||
|  |               num_handles, timeout_ns); | ||||||
|  |  | ||||||
|     // Ensure number of handles is valid. |     // Ensure number of handles is valid. | ||||||
|     R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); |     R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); | ||||||
|  |  | ||||||
|     // Get the synchronization context. |     // Get the synchronization context. | ||||||
|     auto& kernel = system.Kernel(); |     auto& kernel = system.Kernel(); | ||||||
|     auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); |     auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); | ||||||
|     std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs; |     auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); | ||||||
|  |     auto handles = GetCurrentThread(kernel).GetHandleBuffer(); | ||||||
|  |  | ||||||
|     // Copy user handles. |     // Copy user handles. | ||||||
|     if (num_handles > 0) { |     if (num_handles > 0) { | ||||||
|  |         // Ensure we can try to get the handles. | ||||||
|  |         R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( | ||||||
|  |                      user_handles, static_cast<u64>(sizeof(Handle) * num_handles)), | ||||||
|  |                  ResultInvalidPointer); | ||||||
|  |  | ||||||
|  |         // Get the handles. | ||||||
|  |         GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), | ||||||
|  |                                            sizeof(Handle) * num_handles); | ||||||
|  |  | ||||||
|         // Convert the handles to objects. |         // Convert the handles to objects. | ||||||
|         R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, |         R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( | ||||||
|                                                                          num_handles), |                      objs.data(), handles.data(), num_handles), | ||||||
|                  ResultInvalidHandle); |                  ResultInvalidHandle); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -80,23 +94,6 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons | |||||||
|     R_RETURN(res); |     R_RETURN(res); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |  | ||||||
| Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles, |  | ||||||
|                            int32_t num_handles, int64_t timeout_ns) { |  | ||||||
|     LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles, |  | ||||||
|               num_handles, timeout_ns); |  | ||||||
|  |  | ||||||
|     // Ensure number of handles is valid. |  | ||||||
|     R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); |  | ||||||
|     std::array<Handle, Svc::ArgumentHandleCountMax> handles; |  | ||||||
|     if (num_handles > 0) { |  | ||||||
|         GetCurrentMemory(system.Kernel()) |  | ||||||
|             .ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Resumes a thread waiting on WaitSynchronization | /// Resumes a thread waiting on WaitSynchronization | ||||||
| Result CancelSynchronization(Core::System& system, Handle handle) { | Result CancelSynchronization(Core::System& system, Handle handle) { | ||||||
|     LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); |     LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user