From a449e0e11af25b85dfa41c4d774b654637549689 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 26 Nov 2014 14:37:58 -0500 Subject: Mutex: Changed behavior to always release mutex for all threads. --- src/core/hle/kernel/mutex.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 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 b303ba128..d07e9761b 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -88,20 +88,19 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); - bool woke_threads = false; // Find the next waiting thread for the mutex... - while (!woke_threads && !mutex->waiting_threads.empty()) { + while (!mutex->waiting_threads.empty()) { std::vector::iterator iter = mutex->waiting_threads.begin(); - woke_threads |= ReleaseMutexForThread(mutex, *iter); + ReleaseMutexForThread(mutex, *iter); mutex->waiting_threads.erase(iter); } + // Reset mutex lock thread handle, nothing is waiting - if (!woke_threads) { - mutex->locked = false; - mutex->lock_thread = -1; - } - return woke_threads; + mutex->locked = false; + mutex->lock_thread = -1; + + return true; } /** -- cgit v1.2.3 From e3c8e4901c51e2ba172f0e1cec0a07dd56f25311 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 5 Dec 2014 23:40:43 -0500 Subject: Mutex: Properly lock the mutex when a thread enters it Also resume only the next immediate thread waiting for the mutex when it is released, instead of resuming them all. --- src/core/hle/kernel/mutex.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 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 d07e9761b..17850c1b3 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -27,17 +27,13 @@ public: std::vector waiting_threads; ///< Threads that are waiting for the mutex std::string name; ///< Name of mutex (optional) - ResultVal SyncRequest() override { - // TODO(bunnei): ImplementMe - locked = true; - return MakeResult(false); - } - ResultVal WaitSynchronization() override { - // TODO(bunnei): ImplementMe bool wait = locked; if (locked) { Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); + } else { + // Lock the mutex when the first thread accesses it + locked = true; } return MakeResult(wait); @@ -90,16 +86,17 @@ bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); // Find the next waiting thread for the mutex... - while (!mutex->waiting_threads.empty()) { + if (mutex->waiting_threads.empty()) { + // 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); } - // Reset mutex lock thread handle, nothing is waiting - mutex->locked = false; - mutex->lock_thread = -1; - return true; } -- cgit v1.2.3 From 64128aa61a7ada0744f801df116dfbe229a50382 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 7 Dec 2014 15:44:21 -0500 Subject: Mutex: Release all held mutexes when a thread exits. --- src/core/hle/kernel/mutex.cpp | 68 +++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 22 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 17850c1b3..01de3c510 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -13,6 +13,9 @@ namespace Kernel { +class Mutex; +void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThreadHandle()); + class Mutex : public Object { public: std::string GetTypeName() const override { return "Mutex"; } @@ -34,6 +37,7 @@ public: } else { // Lock the mutex when the first thread accesses it locked = true; + MutexAcquireLock(this); } return MakeResult(wait); @@ -45,21 +49,46 @@ public: typedef std::multimap 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 + */ void MutexAcquireLock(Mutex* mutex, Handle thread) { g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); mutex->lock_thread = thread; } -void MutexAcquireLock(Mutex* mutex) { - Handle thread = GetCurrentThreadHandle(); +bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { MutexAcquireLock(mutex, thread); + Kernel::ResumeThreadFromWait(thread); + 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()) { + // 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) { 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) { + if (iter->second == handle) { g_mutex_held_locks.erase(iter); break; } @@ -67,6 +96,19 @@ void MutexEraseLock(Mutex* mutex) { mutex->lock_thread = -1; } +void ReleaseThreadMutexes(Handle 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_object_pool.GetFast(iter->second); + ResumeWaitingThread(mutex); + } + + // Erase all the locks that this thread holds + g_mutex_held_locks.erase(thread); +} + bool LockMutex(Mutex* mutex) { // Mutex alread locked? if (mutex->locked) { @@ -76,27 +118,9 @@ bool LockMutex(Mutex* mutex) { return true; } -bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { - MutexAcquireLock(mutex, thread); - Kernel::ResumeThreadFromWait(thread); - return true; -} - bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); - - // Find the next waiting thread for the mutex... - if (mutex->waiting_threads.empty()) { - // 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); - } - + ResumeWaitingThread(mutex); return true; } -- cgit v1.2.3 From bc318c464bbe1a33e37312339d25c56021c444e8 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 7 Dec 2014 15:57:28 -0500 Subject: Mutex: Remove some forward declarations Moved Mutex::WaitSynchronization to the end of the file. --- src/core/hle/kernel/mutex.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 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 01de3c510..5a173e129 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -13,9 +13,6 @@ namespace Kernel { -class Mutex; -void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThreadHandle()); - class Mutex : public Object { public: std::string GetTypeName() const override { return "Mutex"; } @@ -30,18 +27,7 @@ public: std::vector waiting_threads; ///< Threads that are waiting for the mutex std::string name; ///< Name of mutex (optional) - ResultVal WaitSynchronization() override { - bool wait = locked; - if (locked) { - Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); - } else { - // Lock the mutex when the first thread accesses it - locked = true; - MutexAcquireLock(this); - } - - return MakeResult(wait); - } + ResultVal WaitSynchronization() override; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -54,7 +40,7 @@ static MutexMap g_mutex_held_locks; * @param mutex Mutex that is to be acquired * @param thread Thread that will acquired */ -void MutexAcquireLock(Mutex* mutex, Handle thread) { +void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThreadHandle()) { g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); mutex->lock_thread = thread; } @@ -178,4 +164,17 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { return handle; } +ResultVal Mutex::WaitSynchronization() { + bool wait = locked; + if (locked) { + Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); + } + else { + // Lock the mutex when the first thread accesses it + locked = true; + MutexAcquireLock(this); + } + + return MakeResult(wait); +} } // namespace -- cgit v1.2.3 From ebfd831ccba32bce097491db3d6bdff0be05935e Mon Sep 17 00:00:00 2001 From: purpasmart96 Date: Tue, 16 Dec 2014 21:38:14 -0800 Subject: License change --- 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 5a173e129..5a18af114 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -1,5 +1,5 @@ // Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 +// Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include -- cgit v1.2.3 From 73fba22c019562687c6e14f20ca7422020f7e070 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sat, 13 Dec 2014 21:16:13 -0200 Subject: Rename ObjectPool to HandleTable --- src/core/hle/kernel/mutex.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 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 5a18af114..abfe178a0 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -87,7 +87,7 @@ void ReleaseThreadMutexes(Handle 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_object_pool.GetFast(iter->second); + Mutex* mutex = g_handle_table.GetFast(iter->second); ResumeWaitingThread(mutex); } @@ -115,7 +115,7 @@ bool ReleaseMutex(Mutex* mutex) { * @param handle Handle to mutex to release */ ResultCode ReleaseMutex(Handle handle) { - Mutex* mutex = Kernel::g_object_pool.Get(handle); + Mutex* mutex = Kernel::g_handle_table.Get(handle); if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!ReleaseMutex(mutex)) { @@ -136,7 +136,7 @@ ResultCode ReleaseMutex(Handle handle) { */ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { Mutex* mutex = new Mutex; - handle = Kernel::g_object_pool.Create(mutex); + handle = Kernel::g_handle_table.Create(mutex); mutex->locked = mutex->initial_locked = initial_locked; mutex->name = name; -- cgit v1.2.3 From 23f2142009e45b227867cefe40dfe9d338625974 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 21 Dec 2014 08:40:29 -0200 Subject: Kernel: Replace GetStaticHandleType by HANDLE_TYPE constants --- 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 abfe178a0..08462376d 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -18,8 +18,8 @@ public: std::string GetTypeName() const override { return "Mutex"; } std::string GetName() const override { return name; } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } - Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Mutex; } + static const HandleType HANDLE_TYPE = HandleType::Mutex; + HandleType GetHandleType() const override { return HANDLE_TYPE; } bool initial_locked; ///< Initial lock state when mutex was created bool locked; ///< Current locked state -- cgit v1.2.3 From 7e2903cb74050d846f2da951dff7e84aee13761b Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 21 Dec 2014 10:04:08 -0200 Subject: Kernel: New handle manager This handle manager more closely mirrors the behaviour of the CTR-OS one. In addition object ref-counts and support for DuplicateHandle have been added. Note that support for DuplicateHandle is still experimental, since parts of the kernel still use Handles internally, which will likely cause troubles if two different handles to the same object are used to e.g. wait on a synchronization primitive. --- src/core/hle/kernel/mutex.cpp | 5 +++-- 1 file changed, 3 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 08462376d..558068c79 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -87,7 +87,7 @@ void ReleaseThreadMutexes(Handle 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.GetFast(iter->second); + Mutex* mutex = g_handle_table.Get(iter->second); ResumeWaitingThread(mutex); } @@ -136,7 +136,8 @@ ResultCode ReleaseMutex(Handle handle) { */ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { Mutex* mutex = new Mutex; - handle = Kernel::g_handle_table.Create(mutex); + // TODO(yuriks): Fix error reporting + handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE); mutex->locked = mutex->initial_locked = initial_locked; mutex->name = name; -- cgit v1.2.3