From 75e10578f12cf64bd734388ba80b5f5a46ca6133 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 3 Mar 2020 13:02:50 -0400 Subject: [PATCH] Core: Correct HLE Event Callbacks and other issues. --- src/core/hle/kernel/hle_ipc.cpp | 19 +++++++------ src/core/hle/kernel/svc.cpp | 5 ++-- src/core/hle/kernel/synchronization.cpp | 1 + src/core/hle/kernel/thread.cpp | 37 ++++++++++++------------- src/core/hle/kernel/thread.h | 16 ++++++----- 5 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 955d5fe1c6..e74d91670d 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -21,8 +21,8 @@ #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/readable_event.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/time_manager.h" #include "core/hle/kernel/writable_event.h" @@ -49,14 +49,6 @@ std::shared_ptr HLERequestContext::SleepClientThread( const std::string& reason, u64 timeout, WakeupCallback&& callback, std::shared_ptr writable_event) { // Put the client thread to sleep until the wait event is signaled or the timeout expires. - thread->SetHLECallback( - [context = *this, callback](ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, - std::size_t index) mutable -> bool { - callback(thread, context, reason); - context.WriteToOutgoingCommandBuffer(*thread); - return true; - }); if (!writable_event) { // Create event if not provided @@ -67,6 +59,15 @@ std::shared_ptr HLERequestContext::SleepClientThread( { Handle event_handle = InvalidHandle; SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout); + thread->SetHLECallback( + [context = *this, callback](std::shared_ptr thread) mutable -> bool { + ThreadWakeupReason reason = thread->GetSignalingResult() == RESULT_TIMEOUT + ? ThreadWakeupReason::Timeout + : ThreadWakeupReason::Signal; + callback(thread, context, reason); + context.WriteToOutgoingCommandBuffer(*thread); + return true; + }); const auto readable_event{writable_event->GetReadableEvent()}; writable_event->Clear(); thread->SetStatus(ThreadStatus::WaitHLEEvent); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4c1040a3b9..9f46a17589 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -333,17 +333,16 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { thread->SetStatus(ThreadStatus::WaitIPC); session->SendSyncRequest(SharedFrom(thread), system.Memory()); } - ResultCode result = thread->GetSignalingResult(); if (thread->HasHLECallback()) { Handle event_handle = thread->GetHLETimeEvent(); if (event_handle != InvalidHandle) { auto& time_manager = system.Kernel().TimeManager(); time_manager.UnscheduleTimeEvent(event_handle); } - thread->InvokeHLECallback(ThreadWakeupReason::Timeout, SharedFrom(thread), nullptr, 0); + thread->InvokeHLECallback(SharedFrom(thread)); } - return result; + return RESULT_SUCCESS; } static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index c60c5bb422..4ee7ad93ca 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -28,6 +28,7 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const { time_manager.CancelTimeEvent(thread.get()); } } + obj.ClearWaitingThreads(); } } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index a645ee3a20..16babe71a2 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -47,19 +47,21 @@ Thread::Thread(KernelCore& kernel) : SynchronizationObject{kernel} {} Thread::~Thread() = default; void Thread::Stop() { - SchedulerLock lock(kernel); - // Cancel any outstanding wakeup events for this thread - Signal(); - Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), - global_handle); - kernel.GlobalHandleTable().Close(global_handle); + { + SchedulerLock lock(kernel); + // Cancel any outstanding wakeup events for this thread + Signal(); + Core::System::GetInstance().CoreTiming().UnscheduleEvent( + kernel.ThreadWakeupCallbackEventType(), global_handle); + kernel.GlobalHandleTable().Close(global_handle); + SetStatus(ThreadStatus::Dead); + + owner_process->UnregisterThread(this); + + // Mark the TLS slot in the thread's page as free. + owner_process->FreeTLSRegion(tls_address); + } global_handle = 0; - SetStatus(ThreadStatus::Dead); - - owner_process->UnregisterThread(this); - - // Mark the TLS slot in the thread's page as free. - owner_process->FreeTLSRegion(tls_address); } void Thread::WakeAfterDelay(s64 nanoseconds) { @@ -112,8 +114,6 @@ void Thread::ResumeFromWait() { return; } - hle_callback = nullptr; - if (activity == ThreadActivity::Paused) { SetStatus(ThreadStatus::Paused); return; @@ -398,14 +398,13 @@ bool Thread::AllSynchronizationObjectsReady() const { bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, std::shared_ptr object, std::size_t index) { - ASSERT(hle_callback); - return hle_callback(reason, std::move(thread), std::move(object), index); + ASSERT(wakeup_callback); + return wakeup_callback(reason, std::move(thread), std::move(object), index); } -bool Thread::InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, std::size_t index) { +bool Thread::InvokeHLECallback(std::shared_ptr thread) { ASSERT(hle_callback); - return hle_callback(reason, std::move(thread), std::move(object), index); + return hle_callback(std::move(thread)); } void Thread::SetActivity(ThreadActivity value) { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 04496f96ed..c4c9d69ec9 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -448,7 +448,7 @@ public: } bool HasWakeupCallback() const { - return hle_callback != nullptr; + return wakeup_callback != nullptr; } bool HasHLECallback() const { @@ -456,10 +456,10 @@ public: } void SetWakeupCallback(WakeupCallback callback) { - hle_callback = std::move(callback); + wakeup_callback = std::move(callback); } - void SetHLECallback(WakeupCallback callback) { + void SetHLECallback(HLECallback callback) { hle_callback = std::move(callback); } @@ -487,8 +487,7 @@ public: */ bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, std::shared_ptr object, std::size_t index); - bool InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, std::size_t index); + bool InvokeHLECallback(std::shared_ptr thread); u32 GetIdealCore() const { return ideal_core; @@ -622,8 +621,11 @@ private: /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread /// was waiting via WaitSynchronization then the object will be the last object that became - /// available. In case of a timeout, the object will be nullptr. - WakeupCallback hle_callback; + /// available. In case of a timeout, the object will be nullptr. DEPRECATED + WakeupCallback wakeup_callback; + + /// Callback for HLE Events + HLECallback hle_callback; Handle hle_time_event; Scheduler* scheduler = nullptr;