Просмотр исходного кода

Core: Correct HLE Event Callbacks and other issues.

Fernando Sahmkow 6 лет назад
Родитель
Сommit
75e10578f1

+ 10 - 9
src/core/hle/kernel/hle_ipc.cpp

@@ -21,8 +21,8 @@
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/readable_event.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/scheduler.h"
+#include "core/hle/kernel/server_session.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/time_manager.h"
 #include "core/hle/kernel/time_manager.h"
 #include "core/hle/kernel/writable_event.h"
 #include "core/hle/kernel/writable_event.h"
@@ -49,14 +49,6 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
     const std::string& reason, u64 timeout, WakeupCallback&& callback,
     const std::string& reason, u64 timeout, WakeupCallback&& callback,
     std::shared_ptr<WritableEvent> writable_event) {
     std::shared_ptr<WritableEvent> writable_event) {
     // Put the client thread to sleep until the wait event is signaled or the timeout expires.
     // 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> thread,
-                                    std::shared_ptr<SynchronizationObject> object,
-                                    std::size_t index) mutable -> bool {
-            callback(thread, context, reason);
-            context.WriteToOutgoingCommandBuffer(*thread);
-            return true;
-        });
 
 
     if (!writable_event) {
     if (!writable_event) {
         // Create event if not provided
         // Create event if not provided
@@ -67,6 +59,15 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
     {
     {
         Handle event_handle = InvalidHandle;
         Handle event_handle = InvalidHandle;
         SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
         SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
+        thread->SetHLECallback(
+            [context = *this, callback](std::shared_ptr<Thread> 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()};
         const auto readable_event{writable_event->GetReadableEvent()};
         writable_event->Clear();
         writable_event->Clear();
         thread->SetStatus(ThreadStatus::WaitHLEEvent);
         thread->SetStatus(ThreadStatus::WaitHLEEvent);

+ 2 - 3
src/core/hle/kernel/svc.cpp

@@ -333,17 +333,16 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
         thread->SetStatus(ThreadStatus::WaitIPC);
         thread->SetStatus(ThreadStatus::WaitIPC);
         session->SendSyncRequest(SharedFrom(thread), system.Memory());
         session->SendSyncRequest(SharedFrom(thread), system.Memory());
     }
     }
-    ResultCode result = thread->GetSignalingResult();
     if (thread->HasHLECallback()) {
     if (thread->HasHLECallback()) {
         Handle event_handle = thread->GetHLETimeEvent();
         Handle event_handle = thread->GetHLETimeEvent();
         if (event_handle != InvalidHandle) {
         if (event_handle != InvalidHandle) {
             auto& time_manager = system.Kernel().TimeManager();
             auto& time_manager = system.Kernel().TimeManager();
             time_manager.UnscheduleTimeEvent(event_handle);
             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) {
 static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {

+ 1 - 0
src/core/hle/kernel/synchronization.cpp

@@ -28,6 +28,7 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const {
                 time_manager.CancelTimeEvent(thread.get());
                 time_manager.CancelTimeEvent(thread.get());
             }
             }
         }
         }
+        obj.ClearWaitingThreads();
     }
     }
 }
 }
 
 

+ 17 - 18
src/core/hle/kernel/thread.cpp

@@ -47,19 +47,21 @@ Thread::Thread(KernelCore& kernel) : SynchronizationObject{kernel} {}
 Thread::~Thread() = default;
 Thread::~Thread() = default;
 
 
 void Thread::Stop() {
 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);
-    global_handle = 0;
-    SetStatus(ThreadStatus::Dead);
+    {
+        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);
+        owner_process->UnregisterThread(this);
 
 
-    // Mark the TLS slot in the thread's page as free.
-    owner_process->FreeTLSRegion(tls_address);
+        // Mark the TLS slot in the thread's page as free.
+        owner_process->FreeTLSRegion(tls_address);
+    }
+    global_handle = 0;
 }
 }
 
 
 void Thread::WakeAfterDelay(s64 nanoseconds) {
 void Thread::WakeAfterDelay(s64 nanoseconds) {
@@ -112,8 +114,6 @@ void Thread::ResumeFromWait() {
         return;
         return;
     }
     }
 
 
-    hle_callback = nullptr;
-
     if (activity == ThreadActivity::Paused) {
     if (activity == ThreadActivity::Paused) {
         SetStatus(ThreadStatus::Paused);
         SetStatus(ThreadStatus::Paused);
         return;
         return;
@@ -398,14 +398,13 @@ bool Thread::AllSynchronizationObjectsReady() const {
 bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
 bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
                                   std::shared_ptr<SynchronizationObject> object,
                                   std::shared_ptr<SynchronizationObject> object,
                                   std::size_t index) {
                                   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> thread,
-                               std::shared_ptr<SynchronizationObject> object, std::size_t index) {
+bool Thread::InvokeHLECallback(std::shared_ptr<Thread> thread) {
     ASSERT(hle_callback);
     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) {
 void Thread::SetActivity(ThreadActivity value) {

+ 9 - 7
src/core/hle/kernel/thread.h

@@ -448,7 +448,7 @@ public:
     }
     }
 
 
     bool HasWakeupCallback() const {
     bool HasWakeupCallback() const {
-        return hle_callback != nullptr;
+        return wakeup_callback != nullptr;
     }
     }
 
 
     bool HasHLECallback() const {
     bool HasHLECallback() const {
@@ -456,10 +456,10 @@ public:
     }
     }
 
 
     void SetWakeupCallback(WakeupCallback callback) {
     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);
         hle_callback = std::move(callback);
     }
     }
 
 
@@ -487,8 +487,7 @@ public:
      */
      */
     bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
     bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
                               std::shared_ptr<SynchronizationObject> object, std::size_t index);
                               std::shared_ptr<SynchronizationObject> object, std::size_t index);
-    bool InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
-                           std::shared_ptr<SynchronizationObject> object, std::size_t index);
+    bool InvokeHLECallback(std::shared_ptr<Thread> thread);
 
 
     u32 GetIdealCore() const {
     u32 GetIdealCore() const {
         return ideal_core;
         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
     /// 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
     /// 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;
     Handle hle_time_event;
 
 
     Scheduler* scheduler = nullptr;
     Scheduler* scheduler = nullptr;