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

Kernel: Refactor synchronization to better match RE

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

+ 2 - 0
src/core/CMakeLists.txt

@@ -183,6 +183,8 @@ add_library(core STATIC
     hle/kernel/svc_wrap.h
     hle/kernel/svc_wrap.h
     hle/kernel/synchronization_object.cpp
     hle/kernel/synchronization_object.cpp
     hle/kernel/synchronization_object.h
     hle/kernel/synchronization_object.h
+    hle/kernel/synchronization.cpp
+    hle/kernel/synchronization.h
     hle/kernel/thread.cpp
     hle/kernel/thread.cpp
     hle/kernel/thread.h
     hle/kernel/thread.h
     hle/kernel/transfer_memory.cpp
     hle/kernel/transfer_memory.cpp

+ 5 - 0
src/core/hle/kernel/client_session.cpp

@@ -31,6 +31,11 @@ void ClientSession::Acquire(Thread* thread) {
     UNIMPLEMENTED();
     UNIMPLEMENTED();
 }
 }
 
 
+bool ClientSession::IsSignaled() const {
+    UNIMPLEMENTED();
+    return true;
+}
+
 ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel,
 ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel,
                                                                 std::shared_ptr<Session> parent,
                                                                 std::shared_ptr<Session> parent,
                                                                 std::string name) {
                                                                 std::string name) {

+ 2 - 0
src/core/hle/kernel/client_session.h

@@ -48,6 +48,8 @@ public:
 
 
     void Acquire(Thread* thread) override;
     void Acquire(Thread* thread) override;
 
 
+    bool IsSignaled() const override;
+
 private:
 private:
     static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel,
     static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel,
                                                             std::shared_ptr<Session> parent,
                                                             std::shared_ptr<Session> parent,

+ 12 - 1
src/core/hle/kernel/kernel.cpp

@@ -23,6 +23,7 @@
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/scheduler.h"
+#include "core/hle/kernel/synchronization.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/lock.h"
 #include "core/hle/lock.h"
 #include "core/hle/result.h"
 #include "core/hle/result.h"
@@ -96,7 +97,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
 }
 }
 
 
 struct KernelCore::Impl {
 struct KernelCore::Impl {
-    explicit Impl(Core::System& system) : system{system}, global_scheduler{system} {}
+    explicit Impl(Core::System& system)
+        : system{system}, global_scheduler{system}, synchronization{system} {}
 
 
     void Initialize(KernelCore& kernel) {
     void Initialize(KernelCore& kernel) {
         Shutdown();
         Shutdown();
@@ -191,6 +193,7 @@ struct KernelCore::Impl {
     std::vector<std::shared_ptr<Process>> process_list;
     std::vector<std::shared_ptr<Process>> process_list;
     Process* current_process = nullptr;
     Process* current_process = nullptr;
     Kernel::GlobalScheduler global_scheduler;
     Kernel::GlobalScheduler global_scheduler;
+    Kernel::Synchronization synchronization;
 
 
     std::shared_ptr<ResourceLimit> system_resource_limit;
     std::shared_ptr<ResourceLimit> system_resource_limit;
 
 
@@ -270,6 +273,14 @@ const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
     return impl->cores[id];
     return impl->cores[id];
 }
 }
 
 
+Kernel::Synchronization& KernelCore::Synchronization() {
+    return impl->synchronization;
+}
+
+const Kernel::Synchronization& KernelCore::Synchronization() const {
+    return impl->synchronization;
+}
+
 Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
 Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
     return *impl->exclusive_monitor;
     return *impl->exclusive_monitor;
 }
 }

+ 7 - 0
src/core/hle/kernel/kernel.h

@@ -29,6 +29,7 @@ class HandleTable;
 class PhysicalCore;
 class PhysicalCore;
 class Process;
 class Process;
 class ResourceLimit;
 class ResourceLimit;
+class Synchronization;
 class Thread;
 class Thread;
 
 
 /// Represents a single instance of the kernel.
 /// Represents a single instance of the kernel.
@@ -92,6 +93,12 @@ public:
     /// Gets the an instance of the respective physical CPU core.
     /// Gets the an instance of the respective physical CPU core.
     const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const;
     const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const;
 
 
+    /// Gets the an instance of the Synchronization Interface.
+    Kernel::Synchronization& Synchronization();
+
+    /// Gets the an instance of the Synchronization Interface.
+    const Kernel::Synchronization& Synchronization() const;
+
     /// Stops execution of 'id' core, in order to reschedule a new thread.
     /// Stops execution of 'id' core, in order to reschedule a new thread.
     void PrepareReschedule(std::size_t id);
     void PrepareReschedule(std::size_t id);
 
 

+ 1 - 1
src/core/hle/kernel/process.cpp

@@ -357,7 +357,7 @@ void Process::ChangeStatus(ProcessStatus new_status) {
 
 
     status = new_status;
     status = new_status;
     is_signaled = true;
     is_signaled = true;
-    WakeupAllWaitingThreads();
+    Signal();
 }
 }
 
 
 void Process::AllocateMainThreadStack(u64 stack_size) {
 void Process::AllocateMainThreadStack(u64 stack_size) {

+ 0 - 4
src/core/hle/kernel/process.h

@@ -359,10 +359,6 @@ private:
     /// specified by metadata provided to the process during loading.
     /// specified by metadata provided to the process during loading.
     bool is_64bit_process = true;
     bool is_64bit_process = true;
 
 
-    /// Whether or not this process is signaled. This occurs
-    /// upon the process changing to a different state.
-    bool is_signaled = false;
-
     /// Total running time for the process in ticks.
     /// Total running time for the process in ticks.
     u64 total_process_running_time_ticks = 0;
     u64 total_process_running_time_ticks = 0;
 
 

+ 7 - 7
src/core/hle/kernel/readable_event.cpp

@@ -15,26 +15,26 @@ ReadableEvent::ReadableEvent(KernelCore& kernel) : SynchronizationObject{kernel}
 ReadableEvent::~ReadableEvent() = default;
 ReadableEvent::~ReadableEvent() = default;
 
 
 bool ReadableEvent::ShouldWait(const Thread* thread) const {
 bool ReadableEvent::ShouldWait(const Thread* thread) const {
-    return !signaled;
+    return !is_signaled;
 }
 }
 
 
 void ReadableEvent::Acquire(Thread* thread) {
 void ReadableEvent::Acquire(Thread* thread) {
-    ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
+    ASSERT_MSG(IsSignaled(), "object unavailable!");
 }
 }
 
 
 void ReadableEvent::Signal() {
 void ReadableEvent::Signal() {
-    if (!signaled) {
-        signaled = true;
-        WakeupAllWaitingThreads();
+    if (!is_signaled) {
+        is_signaled = true;
+        SynchronizationObject::Signal();
     };
     };
 }
 }
 
 
 void ReadableEvent::Clear() {
 void ReadableEvent::Clear() {
-    signaled = false;
+    is_signaled = false;
 }
 }
 
 
 ResultCode ReadableEvent::Reset() {
 ResultCode ReadableEvent::Reset() {
-    if (!signaled) {
+    if (!is_signaled) {
         return ERR_INVALID_STATE;
         return ERR_INVALID_STATE;
     }
     }
 
 

+ 2 - 4
src/core/hle/kernel/readable_event.h

@@ -46,13 +46,11 @@ public:
     ///      then ERR_INVALID_STATE will be returned.
     ///      then ERR_INVALID_STATE will be returned.
     ResultCode Reset();
     ResultCode Reset();
 
 
+    void Signal() override;
+
 private:
 private:
     explicit ReadableEvent(KernelCore& kernel);
     explicit ReadableEvent(KernelCore& kernel);
 
 
-    void Signal();
-
-    bool signaled{};
-
     std::string name; ///< Name of event (optional)
     std::string name; ///< Name of event (optional)
 };
 };
 
 

+ 4 - 0
src/core/hle/kernel/server_port.cpp

@@ -39,6 +39,10 @@ void ServerPort::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
 }
 }
 
 
+bool ServerPort::IsSignaled() const {
+    return !pending_sessions.empty();
+}
+
 ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions,
 ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions,
                                                 std::string name) {
                                                 std::string name) {
     std::shared_ptr<ServerPort> server_port = std::make_shared<ServerPort>(kernel);
     std::shared_ptr<ServerPort> server_port = std::make_shared<ServerPort>(kernel);

+ 2 - 0
src/core/hle/kernel/server_port.h

@@ -82,6 +82,8 @@ public:
     bool ShouldWait(const Thread* thread) const override;
     bool ShouldWait(const Thread* thread) const override;
     void Acquire(Thread* thread) override;
     void Acquire(Thread* thread) override;
 
 
+    bool IsSignaled() const override;
+
 private:
 private:
     /// ServerSessions waiting to be accepted by the port
     /// ServerSessions waiting to be accepted by the port
     std::vector<std::shared_ptr<ServerSession>> pending_sessions;
     std::vector<std::shared_ptr<ServerSession>> pending_sessions;

+ 10 - 0
src/core/hle/kernel/server_session.cpp

@@ -50,6 +50,16 @@ bool ServerSession::ShouldWait(const Thread* thread) const {
     return pending_requesting_threads.empty() || currently_handling != nullptr;
     return pending_requesting_threads.empty() || currently_handling != nullptr;
 }
 }
 
 
+bool ServerSession::IsSignaled() const {
+    // Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
+    if (!parent->Client()) {
+        return true;
+    }
+
+    // Wait if we have no pending requests, or if we're currently handling a request.
+    return !(pending_requesting_threads.empty() || currently_handling != nullptr);
+}
+
 void ServerSession::Acquire(Thread* thread) {
 void ServerSession::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
     // We are now handling a request, pop it from the stack.
     // We are now handling a request, pop it from the stack.

+ 2 - 0
src/core/hle/kernel/server_session.h

@@ -73,6 +73,8 @@ public:
         return parent.get();
         return parent.get();
     }
     }
 
 
+    bool IsSignaled() const override;
+
     /**
     /**
      * Sets the HLE handler for the session. This handler will be called to service IPC requests
      * Sets the HLE handler for the session. This handler will be called to service IPC requests
      * instead of the regular IPC machinery. (The regular IPC machinery is currently not
      * instead of the regular IPC machinery. (The regular IPC machinery is currently not

+ 5 - 0
src/core/hle/kernel/session.cpp

@@ -29,6 +29,11 @@ bool Session::ShouldWait(const Thread* thread) const {
     return {};
     return {};
 }
 }
 
 
+bool Session::IsSignaled() const {
+    UNIMPLEMENTED();
+    return true;
+}
+
 void Session::Acquire(Thread* thread) {
 void Session::Acquire(Thread* thread) {
     UNIMPLEMENTED();
     UNIMPLEMENTED();
 }
 }

+ 2 - 0
src/core/hle/kernel/session.h

@@ -39,6 +39,8 @@ public:
 
 
     bool ShouldWait(const Thread* thread) const override;
     bool ShouldWait(const Thread* thread) const override;
 
 
+    bool IsSignaled() const override;
+
     void Acquire(Thread* thread) override;
     void Acquire(Thread* thread) override;
 
 
     std::shared_ptr<ClientSession> Client() {
     std::shared_ptr<ClientSession> Client() {

+ 7 - 60
src/core/hle/kernel/svc.cpp

@@ -32,6 +32,7 @@
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/kernel/svc.h"
 #include "core/hle/kernel/svc.h"
 #include "core/hle/kernel/svc_wrap.h"
 #include "core/hle/kernel/svc_wrap.h"
+#include "core/hle/kernel/synchronization.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/transfer_memory.h"
 #include "core/hle/kernel/transfer_memory.h"
 #include "core/hle/kernel/writable_event.h"
 #include "core/hle/kernel/writable_event.h"
@@ -433,23 +434,6 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
     return ERR_INVALID_HANDLE;
     return ERR_INVALID_HANDLE;
 }
 }
 
 
-/// Default thread wakeup callback for WaitSynchronization
-static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
-                                        std::shared_ptr<SynchronizationObject> object,
-                                        std::size_t index) {
-    ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
-
-    if (reason == ThreadWakeupReason::Timeout) {
-        thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
-        return true;
-    }
-
-    ASSERT(reason == ThreadWakeupReason::Signal);
-    thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
-    thread->SetWaitSynchronizationOutput(static_cast<u32>(index));
-    return true;
-};
-
 /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
 /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
 static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address,
 static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address,
                                       u64 handle_count, s64 nano_seconds) {
                                       u64 handle_count, s64 nano_seconds) {
@@ -473,10 +457,10 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
     }
     }
 
 
     auto* const thread = system.CurrentScheduler().GetCurrentThread();
     auto* const thread = system.CurrentScheduler().GetCurrentThread();
-
+    auto& kernel = system.Kernel();
     using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type;
     using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type;
     Thread::ThreadSynchronizationObjects objects(handle_count);
     Thread::ThreadSynchronizationObjects objects(handle_count);
-    const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
+    const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
 
 
     for (u64 i = 0; i < handle_count; ++i) {
     for (u64 i = 0; i < handle_count; ++i) {
         const Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
         const Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
@@ -489,47 +473,10 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
 
 
         objects[i] = object;
         objects[i] = object;
     }
     }
-
-    // Find the first object that is acquirable in the provided list of objects
-    auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) {
-        return !object->ShouldWait(thread);
-    });
-
-    if (itr != objects.end()) {
-        // We found a ready object, acquire it and set the result value
-        SynchronizationObject* object = itr->get();
-        object->Acquire(thread);
-        *index = static_cast<s32>(std::distance(objects.begin(), itr));
-        return RESULT_SUCCESS;
-    }
-
-    // No objects were ready to be acquired, prepare to suspend the thread.
-
-    // If a timeout value of 0 was provided, just return the Timeout error code instead of
-    // suspending the thread.
-    if (nano_seconds == 0) {
-        return RESULT_TIMEOUT;
-    }
-
-    if (thread->IsSyncCancelled()) {
-        thread->SetSyncCancelled(false);
-        return ERR_SYNCHRONIZATION_CANCELED;
-    }
-
-    for (auto& object : objects) {
-        object->AddWaitingThread(SharedFrom(thread));
-    }
-
-    thread->SetSynchronizationObjects(std::move(objects));
-    thread->SetStatus(ThreadStatus::WaitSynch);
-
-    // Create an event to wake the thread up after the specified nanosecond delay has passed
-    thread->WakeAfterDelay(nano_seconds);
-    thread->SetWakeupCallback(DefaultThreadWakeupCallback);
-
-    system.PrepareReschedule(thread->GetProcessorID());
-
-    return RESULT_TIMEOUT;
+    auto& synchronization = kernel.Synchronization();
+    auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds);
+    *index = handle_result;
+    return result;
 }
 }
 
 
 /// Resumes a thread waiting on WaitSynchronization
 /// Resumes a thread waiting on WaitSynchronization

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

@@ -0,0 +1,86 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/core.h"
+#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/scheduler.h"
+#include "core/hle/kernel/synchronization.h"
+#include "core/hle/kernel/synchronization_object.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+/// Default thread wakeup callback for WaitSynchronization
+static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
+                                        std::shared_ptr<SynchronizationObject> object,
+                                        std::size_t index) {
+    ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
+
+    if (reason == ThreadWakeupReason::Timeout) {
+        thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
+        return true;
+    }
+
+    ASSERT(reason == ThreadWakeupReason::Signal);
+    thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
+    thread->SetWaitSynchronizationOutput(static_cast<u32>(index));
+    return true;
+};
+
+Synchronization::Synchronization(Core::System& system) : system{system} {}
+
+void Synchronization::SignalObject(SynchronizationObject& obj) const {
+    if (obj.IsSignaled()) {
+        obj.WakeupAllWaitingThreads();
+    };
+}
+
+std::pair<ResultCode, Handle> Synchronization::WaitFor(
+    std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) {
+    auto* const thread = system.CurrentScheduler().GetCurrentThread();
+    // Find the first object that is acquirable in the provided list of objects
+    auto itr = std::find_if(sync_objects.begin(), sync_objects.end(),
+                            [thread](const std::shared_ptr<SynchronizationObject>& object) {
+                                return object->IsSignaled();
+                            });
+
+    if (itr != sync_objects.end()) {
+        // We found a ready object, acquire it and set the result value
+        SynchronizationObject* object = itr->get();
+        object->Acquire(thread);
+        u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr));
+        return {RESULT_SUCCESS, index};
+    }
+
+    // No objects were ready to be acquired, prepare to suspend the thread.
+
+    // If a timeout value of 0 was provided, just return the Timeout error code instead of
+    // suspending the thread.
+    if (nano_seconds == 0) {
+        return {RESULT_TIMEOUT, 0};
+    }
+
+    if (thread->IsSyncCancelled()) {
+        thread->SetSyncCancelled(false);
+        return {ERR_SYNCHRONIZATION_CANCELED, 0};
+    }
+
+    for (auto& object : sync_objects) {
+        object->AddWaitingThread(SharedFrom(thread));
+    }
+
+    thread->SetSynchronizationObjects(std::move(sync_objects));
+    thread->SetStatus(ThreadStatus::WaitSynch);
+
+    // Create an event to wake the thread up after the specified nanosecond delay has passed
+    thread->WakeAfterDelay(nano_seconds);
+    thread->SetWakeupCallback(DefaultThreadWakeupCallback);
+
+    system.PrepareReschedule(thread->GetProcessorID());
+
+    return {RESULT_TIMEOUT, 0};
+}
+
+} // namespace Kernel

+ 34 - 0
src/core/hle/kernel/synchronization.h

@@ -0,0 +1,34 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <utility>
+
+#include "core/hle/kernel/object.h"
+#include "core/hle/result.h"
+
+namespace Core {
+class System;
+} // namespace Core
+
+namespace Kernel {
+
+class KernelCore;
+class SynchronizationObject;
+
+class Synchronization {
+public:
+    Synchronization(Core::System& system);
+
+    void SignalObject(SynchronizationObject& obj) const;
+
+    std::pair<ResultCode, Handle> WaitFor(
+        std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds);
+
+private:
+    Core::System& system;
+};
+} // namespace Kernel

+ 5 - 0
src/core/hle/kernel/synchronization_object.cpp

@@ -10,6 +10,7 @@
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/kernel.h"
 #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/synchronization.h"
 #include "core/hle/kernel/synchronization_object.h"
 #include "core/hle/kernel/synchronization_object.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/thread.h"
 
 
@@ -18,6 +19,10 @@ namespace Kernel {
 SynchronizationObject::SynchronizationObject(KernelCore& kernel) : Object{kernel} {}
 SynchronizationObject::SynchronizationObject(KernelCore& kernel) : Object{kernel} {}
 SynchronizationObject::~SynchronizationObject() = default;
 SynchronizationObject::~SynchronizationObject() = default;
 
 
+void SynchronizationObject::Signal() {
+    kernel.Synchronization().SignalObject(*this);
+}
+
 void SynchronizationObject::AddWaitingThread(std::shared_ptr<Thread> thread) {
 void SynchronizationObject::AddWaitingThread(std::shared_ptr<Thread> thread) {
     auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
     auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
     if (itr == waiting_threads.end())
     if (itr == waiting_threads.end())

+ 10 - 0
src/core/hle/kernel/synchronization_object.h

@@ -30,6 +30,13 @@ public:
     /// Acquire/lock the object for the specified thread if it is available
     /// Acquire/lock the object for the specified thread if it is available
     virtual void Acquire(Thread* thread) = 0;
     virtual void Acquire(Thread* thread) = 0;
 
 
+    /// Signal this object
+    virtual void Signal();
+
+    virtual bool IsSignaled() const {
+        return is_signaled;
+    }
+
     /**
     /**
      * Add a thread to wait on this object
      * Add a thread to wait on this object
      * @param thread Pointer to thread to add
      * @param thread Pointer to thread to add
@@ -60,6 +67,9 @@ public:
     /// Get a const reference to the waiting threads list for debug use
     /// Get a const reference to the waiting threads list for debug use
     const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const;
     const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const;
 
 
+protected:
+    bool is_signaled{}; // Tells if this sync object is signalled;
+
 private:
 private:
     /// Threads waiting for this object to become available
     /// Threads waiting for this object to become available
     std::vector<std::shared_ptr<Thread>> waiting_threads;
     std::vector<std::shared_ptr<Thread>> waiting_threads;

+ 5 - 1
src/core/hle/kernel/thread.cpp

@@ -31,6 +31,10 @@ bool Thread::ShouldWait(const Thread* thread) const {
     return status != ThreadStatus::Dead;
     return status != ThreadStatus::Dead;
 }
 }
 
 
+bool Thread::IsSignaled() const {
+    return status == ThreadStatus::Dead;
+}
+
 void Thread::Acquire(Thread* thread) {
 void Thread::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
 }
 }
@@ -45,7 +49,7 @@ void Thread::Stop() {
     kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle);
     kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle);
     callback_handle = 0;
     callback_handle = 0;
     SetStatus(ThreadStatus::Dead);
     SetStatus(ThreadStatus::Dead);
-    WakeupAllWaitingThreads();
+    Signal();
 
 
     // Clean up any dangling references in objects that this thread was waiting for
     // Clean up any dangling references in objects that this thread was waiting for
     for (auto& wait_object : wait_objects) {
     for (auto& wait_object : wait_objects) {

+ 1 - 0
src/core/hle/kernel/thread.h

@@ -146,6 +146,7 @@ public:
 
 
     bool ShouldWait(const Thread* thread) const override;
     bool ShouldWait(const Thread* thread) const override;
     void Acquire(Thread* thread) override;
     void Acquire(Thread* thread) override;
+    bool IsSignaled() const override;
 
 
     /**
     /**
      * Gets the thread's current priority
      * Gets the thread's current priority

+ 1 - 2
src/core/hle/kernel/writable_event.cpp

@@ -22,7 +22,6 @@ EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
     writable_event->name = name + ":Writable";
     writable_event->name = name + ":Writable";
     writable_event->readable = readable_event;
     writable_event->readable = readable_event;
     readable_event->name = name + ":Readable";
     readable_event->name = name + ":Readable";
-    readable_event->signaled = false;
 
 
     return {std::move(readable_event), std::move(writable_event)};
     return {std::move(readable_event), std::move(writable_event)};
 }
 }
@@ -40,7 +39,7 @@ void WritableEvent::Clear() {
 }
 }
 
 
 bool WritableEvent::IsSignaled() const {
 bool WritableEvent::IsSignaled() const {
-    return readable->signaled;
+    return readable->IsSignaled();
 }
 }
 
 
 } // namespace Kernel
 } // namespace Kernel