diff options
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_ipc.cpp | 37 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_synchronization.cpp | 41 | 
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:          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;      void SetInterruptFlag();      void ClearInterruptFlag(); @@ -855,6 +864,7 @@ private:      u32* m_light_ipc_data{};      KProcessAddress m_tls_address{};      KLightLock m_activity_pause_lock; +    SyncObjectBuffer m_sync_object_buffer{};      s64 m_schedule_count{};      s64 m_last_scheduled_tick{};      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  Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,                         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& handle_table = GetCurrentProcess(kernel).GetHandleTable(); - -    R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); -    R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( -                 handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), -             ResultInvalidPointer); - -    std::array<Handle, Svc::ArgumentHandleCountMax> handles; -    GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles); - -    // Convert handle list to object table. -    std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs; -    R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(), -                                                                     num_handles), -             ResultInvalidHandle); +    auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); +    auto handles = GetCurrentThread(kernel).GetHandleBuffer(); + +    // Copy user handles. +    if (num_handles > 0) { +        // Ensure we can try to get the handles. +        R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( +                     handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), +                 ResultInvalidPointer); + +        // Get the handles. +        GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), +                                           sizeof(Handle) * num_handles); + +        // Convert the handles to objects. +        R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( +                     objs.data(), handles.data(), num_handles), +                 ResultInvalidHandle); +    }      // Ensure handles are closed when we're done.      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) {      R_THROW(ResultInvalidHandle);  } -static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles, -                                  int32_t num_handles, int64_t timeout_ns) { +/// 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);      // Get the synchronization context.      auto& kernel = system.Kernel();      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.      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. -        R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, -                                                                         num_handles), +        R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( +                     objs.data(), handles.data(), num_handles),                   ResultInvalidHandle);      } @@ -80,23 +94,6 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons      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  Result CancelSynchronization(Core::System& system, Handle handle) {      LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); | 
