From c22bac6398ff1705992fc44b2c29775c84cff662 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 14 Jan 2015 19:22:50 -0500 Subject: Kernel: Added WaitObject and changed "waitable" objects inherit from it. --- src/core/hle/kernel/mutex.cpp | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 853a5dd74..35d829606 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -13,7 +13,7 @@ namespace Kernel { -class Mutex : public Object { +class Mutex : public WaitObject { public: std::string GetTypeName() const override { return "Mutex"; } std::string GetName() const override { return name; } @@ -24,7 +24,6 @@ public: bool initial_locked; ///< Initial lock state when mutex was created bool locked; ///< Current locked state Handle lock_thread; ///< Handle to thread that currently has mutex - std::vector waiting_threads; ///< Threads that are waiting for the mutex std::string name; ///< Name of mutex (optional) ResultVal WaitSynchronization() override; @@ -45,36 +44,20 @@ void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandl mutex->lock_thread = thread; } -bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) { - MutexAcquireLock(mutex, thread_handle); - - Thread* thread = Kernel::g_handle_table.Get(thread_handle).get(); - if (thread == nullptr) { - LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle); - return false; - } - - thread->ResumeFromWait(); - return true; -} - /** * Resumes a thread waiting for the specified mutex * @param mutex The mutex that some thread is waiting on */ void ResumeWaitingThread(Mutex* mutex) { // Find the next waiting thread for the mutex... - if (mutex->waiting_threads.empty()) { + auto next_thread = mutex->ResumeNextThread(); + if (next_thread != nullptr) { + MutexAcquireLock(mutex, next_thread->GetHandle()); + } else { // Reset mutex lock thread handle, nothing is waiting mutex->locked = false; mutex->lock_thread = -1; } - else { - // Resume the next waiting thread and re-lock the mutex - std::vector::iterator iter = mutex->waiting_threads.begin(); - ReleaseMutexForThread(mutex, *iter); - mutex->waiting_threads.erase(iter); - } } void MutexEraseLock(Mutex* mutex) { @@ -175,7 +158,7 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { ResultVal Mutex::WaitSynchronization() { bool wait = locked; if (locked) { - waiting_threads.push_back(GetCurrentThread()->GetHandle()); + AddWaitingThread(GetCurrentThread()); Kernel::WaitCurrentThread(WAITTYPE_MUTEX, this); } else { // Lock the mutex when the first thread accesses it -- cgit v1.2.3 From 7faf2d8e06e705d1866fa0d7848ff43541a4b172 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 17 Jan 2015 02:03:44 -0500 Subject: WaitSynchronizationN: Implement return values --- src/core/hle/kernel/mutex.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 35d829606..78063b8f1 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -26,7 +26,7 @@ public: Handle lock_thread; ///< Handle to thread that currently has mutex std::string name; ///< Name of mutex (optional) - ResultVal WaitSynchronization() override; + ResultVal WaitSynchronization(unsigned index) override; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -50,7 +50,7 @@ void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandl */ void ResumeWaitingThread(Mutex* mutex) { // Find the next waiting thread for the mutex... - auto next_thread = mutex->ResumeNextThread(); + auto next_thread = mutex->ReleaseNextThread(); if (next_thread != nullptr) { MutexAcquireLock(mutex, next_thread->GetHandle()); } else { @@ -155,11 +155,11 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } -ResultVal Mutex::WaitSynchronization() { +ResultVal Mutex::WaitSynchronization(unsigned index) { bool wait = locked; if (locked) { AddWaitingThread(GetCurrentThread()); - Kernel::WaitCurrentThread(WAITTYPE_MUTEX, this); + Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_MUTEX, this, index); } else { // Lock the mutex when the first thread accesses it locked = true; -- cgit v1.2.3 From aa01c57ae9d73e41b65d37860ca6fbb91caba33a Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 17 Jan 2015 22:23:49 -0500 Subject: Kernel: Separate WaitSynchronization into Wait and Acquire methods. --- src/core/hle/kernel/mutex.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 78063b8f1..37e7be4e7 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -26,7 +26,8 @@ public: Handle lock_thread; ///< Handle to thread that currently has mutex std::string name; ///< Name of mutex (optional) - ResultVal WaitSynchronization(unsigned index) override; + ResultVal Wait(unsigned index) override; + ResultVal Acquire() override; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -155,17 +156,25 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } -ResultVal Mutex::WaitSynchronization(unsigned index) { - bool wait = locked; +ResultVal Mutex::Wait(unsigned index) { if (locked) { AddWaitingThread(GetCurrentThread()); Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_MUTEX, this, index); - } else { + } + + return MakeResult(locked); +} + +ResultVal Mutex::Acquire() { + bool res = false; + + if (!locked) { // Lock the mutex when the first thread accesses it locked = true; + res = true; MutexAcquireLock(this); } - return MakeResult(wait); + return MakeResult(res); } } // namespace -- cgit v1.2.3 From 6643673f28b9273149fc945849a13ed832e9ef33 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 Jan 2015 01:27:46 -0500 Subject: WaitSynchronizationN: Refactor to fix several bugs - Separate wait checking from waiting the current thread - Resume thread when wait_all=true only if all objects are available at once - Set output to correct wait object index when there are duplicate handles --- src/core/hle/kernel/mutex.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 37e7be4e7..f97c69a78 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -26,7 +26,7 @@ public: Handle lock_thread; ///< Handle to thread that currently has mutex std::string name; ///< Name of mutex (optional) - ResultVal Wait(unsigned index) override; + ResultVal Wait(bool wait_thread) override; ResultVal Acquire() override; }; @@ -156,10 +156,10 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } -ResultVal Mutex::Wait(unsigned index) { - if (locked) { +ResultVal Mutex::Wait(bool wait_thread) { + if (locked && wait_thread) { AddWaitingThread(GetCurrentThread()); - Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_MUTEX, this, index); + Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_MUTEX, this); } return MakeResult(locked); -- cgit v1.2.3 From e5a9f1c64483e01b7856c581ae5685d0c5ad88dc Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 Jan 2015 13:25:51 -0500 Subject: Kernel: Get rid of WaitTypes and simplify lots of code, removing hacks. --- src/core/hle/kernel/mutex.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index f97c69a78..4a1eaca37 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -26,7 +26,7 @@ public: Handle lock_thread; ///< Handle to thread that currently has mutex std::string name; ///< Name of mutex (optional) - ResultVal Wait(bool wait_thread) override; + ResultVal Wait() override; ResultVal Acquire() override; }; @@ -156,12 +156,7 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } -ResultVal Mutex::Wait(bool wait_thread) { - if (locked && wait_thread) { - AddWaitingThread(GetCurrentThread()); - Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_MUTEX, this); - } - +ResultVal Mutex::Wait() { return MakeResult(locked); } -- cgit v1.2.3 From dde02f79af45fc01d747254eefbe680e580c3d45 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 Jan 2015 15:45:01 -0500 Subject: Mutex: Fix a bug where the thread should not wait if it already has the mutex. --- src/core/hle/kernel/mutex.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 4a1eaca37..6cd140376 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -25,6 +25,7 @@ public: bool locked; ///< Current locked state Handle lock_thread; ///< Handle to thread that currently has mutex std::string name; ///< Name of mutex (optional) + SharedPtr current_thread; ///< Thread that has acquired the mutex ResultVal Wait() override; ResultVal Acquire() override; @@ -43,6 +44,7 @@ static MutexMap g_mutex_held_locks; void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandle()) { g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); mutex->lock_thread = thread; + mutex->current_thread = Kernel::g_handle_table.Get(thread); } /** @@ -132,6 +134,7 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) mutex->locked = mutex->initial_locked = initial_locked; mutex->name = name; + mutex->current_thread = nullptr; // Acquire mutex with current thread if initialized as locked... if (mutex->locked) { @@ -157,7 +160,7 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { } ResultVal Mutex::Wait() { - return MakeResult(locked); + return MakeResult(locked && (current_thread != GetCurrentThread())); } ResultVal Mutex::Acquire() { -- cgit v1.2.3 From c68eb1569549ae49ae25c6c29cec2e10d8329f2d Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 Jan 2015 17:41:12 -0500 Subject: WaitObject: Renamed "Wait" to "ShouldWait", made "ShouldWait" and "Acquire" pure virtual. --- src/core/hle/kernel/mutex.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 6cd140376..01d2263ff 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -27,7 +27,7 @@ public: std::string name; ///< Name of mutex (optional) SharedPtr current_thread; ///< Thread that has acquired the mutex - ResultVal Wait() override; + ResultVal ShouldWait() override; ResultVal Acquire() override; }; @@ -159,7 +159,7 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } -ResultVal Mutex::Wait() { +ResultVal Mutex::ShouldWait() { return MakeResult(locked && (current_thread != GetCurrentThread())); } -- cgit v1.2.3 From 15b6a4d9add6b260a2a1a84ab6228addced4f851 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 Jan 2015 18:16:45 -0500 Subject: Kernel: Changed "ShouldWait" to return bool and "Acquire" to return void. --- src/core/hle/kernel/mutex.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 01d2263ff..355824e60 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -27,8 +27,8 @@ public: std::string name; ///< Name of mutex (optional) SharedPtr current_thread; ///< Thread that has acquired the mutex - ResultVal ShouldWait() override; - ResultVal Acquire() override; + bool ShouldWait() override; + void Acquire() override; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -159,20 +159,14 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } -ResultVal Mutex::ShouldWait() { - return MakeResult(locked && (current_thread != GetCurrentThread())); +bool Mutex::ShouldWait() { + return locked && current_thread != GetCurrentThread(); } -ResultVal Mutex::Acquire() { - bool res = false; - - if (!locked) { - // Lock the mutex when the first thread accesses it - locked = true; - res = true; - MutexAcquireLock(this); - } - - return MakeResult(res); +void Mutex::Acquire() { + _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); + locked = true; + MutexAcquireLock(this); } + } // namespace -- cgit v1.2.3 From f09806aed24b2f7de7d969cbfdb3b9d18ab90c61 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 Jan 2015 18:20:47 -0500 Subject: Kernel: Renamed some functions for clarity. - ReleaseNextThread->WakeupNextThread - ReleaseAllWaitingThreads->WakeupAllWaitingThreads. --- src/core/hle/kernel/mutex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 355824e60..c170e55ff 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -53,7 +53,7 @@ void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandl */ void ResumeWaitingThread(Mutex* mutex) { // Find the next waiting thread for the mutex... - auto next_thread = mutex->ReleaseNextThread(); + auto next_thread = mutex->WakeupNextThread(); if (next_thread != nullptr) { MutexAcquireLock(mutex, next_thread->GetHandle()); } else { -- cgit v1.2.3 From 2f3020a10247a0cb47848a6f8c19fbde50a7e0a6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 Jan 2015 18:33:23 -0500 Subject: Mutex: Cleanup and remove redundant code. --- src/core/hle/kernel/mutex.cpp | 72 ++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 45 deletions(-) (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index c170e55ff..cd05a1397 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -23,9 +23,8 @@ public: bool initial_locked; ///< Initial lock state when mutex was created bool locked; ///< Current locked state - Handle lock_thread; ///< Handle to thread that currently has mutex std::string name; ///< Name of mutex (optional) - SharedPtr current_thread; ///< Thread that has acquired the mutex + SharedPtr holding_thread; ///< Thread that has acquired the mutex bool ShouldWait() override; void Acquire() override; @@ -33,18 +32,17 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////// -typedef std::multimap MutexMap; +typedef std::multimap, SharedPtr> MutexMap; static MutexMap g_mutex_held_locks; /** * Acquires the specified mutex for the specified thread * @param mutex Mutex that is to be acquired - * @param thread Thread that will acquired + * @param thread Thread that will acquire the mutex */ -void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandle()) { - g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); - mutex->lock_thread = thread; - mutex->current_thread = Kernel::g_handle_table.Get(thread); +void MutexAcquireLock(Mutex* mutex, Thread* thread) { + g_mutex_held_locks.insert(std::make_pair(thread, mutex)); + mutex->holding_thread = thread; } /** @@ -55,51 +53,39 @@ void ResumeWaitingThread(Mutex* mutex) { // Find the next waiting thread for the mutex... auto next_thread = mutex->WakeupNextThread(); if (next_thread != nullptr) { - MutexAcquireLock(mutex, next_thread->GetHandle()); + MutexAcquireLock(mutex, next_thread); } else { // Reset mutex lock thread handle, nothing is waiting mutex->locked = false; - mutex->lock_thread = -1; + mutex->holding_thread = nullptr; } } -void MutexEraseLock(Mutex* mutex) { - Handle handle = mutex->GetHandle(); - auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread); - for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { - if (iter->second == handle) { - g_mutex_held_locks.erase(iter); - break; - } - } - mutex->lock_thread = -1; -} - -void ReleaseThreadMutexes(Handle thread) { +void ReleaseThreadMutexes(Thread* thread) { auto locked = g_mutex_held_locks.equal_range(thread); // Release every mutex that the thread holds, and resume execution on the waiting threads - for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { - Mutex* mutex = g_handle_table.Get(iter->second).get(); - ResumeWaitingThread(mutex); + for (auto iter = locked.first; iter != locked.second; ++iter) { + ResumeWaitingThread(iter->second.get()); } // Erase all the locks that this thread holds g_mutex_held_locks.erase(thread); } -bool LockMutex(Mutex* mutex) { - // Mutex alread locked? +bool ReleaseMutex(Mutex* mutex) { if (mutex->locked) { - return false; - } - MutexAcquireLock(mutex); - return true; -} + auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); -bool ReleaseMutex(Mutex* mutex) { - MutexEraseLock(mutex); - ResumeWaitingThread(mutex); + for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { + if (iter->second == mutex) { + g_mutex_held_locks.erase(iter); + break; + } + } + + ResumeWaitingThread(mutex); + } return true; } @@ -134,16 +120,12 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) mutex->locked = mutex->initial_locked = initial_locked; mutex->name = name; - mutex->current_thread = nullptr; + mutex->holding_thread = nullptr; // Acquire mutex with current thread if initialized as locked... - if (mutex->locked) { - MutexAcquireLock(mutex); + if (mutex->locked) + MutexAcquireLock(mutex, GetCurrentThread()); - // Otherwise, reset lock thread handle - } else { - mutex->lock_thread = -1; - } return mutex; } @@ -160,13 +142,13 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { } bool Mutex::ShouldWait() { - return locked && current_thread != GetCurrentThread(); + return locked && holding_thread != GetCurrentThread(); } void Mutex::Acquire() { _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); locked = true; - MutexAcquireLock(this); + MutexAcquireLock(this, GetCurrentThread()); } } // namespace -- cgit v1.2.3