From 978e1d4653cd12a68d6bfa05af57edb1645da0f5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 23:03:45 -0400 Subject: mutex: initial commit of HLE module --- src/core/hle/kernel/mutex.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 src/core/hle/kernel/mutex.cpp (limited to 'src/core/hle/kernel/mutex.cpp') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp new file mode 100644 index 000000000..2b2cff4ea --- /dev/null +++ b/src/core/hle/kernel/mutex.cpp @@ -0,0 +1,122 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "common/common.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +class Mutex : public Object { +public: + const char* GetTypeName() { return "Mutex"; } + + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } + + 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 +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef std::multimap MutexMap; +static MutexMap g_mutex_held_locks; + +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 = GetCurrentThread(); + __MutexAcquireLock(mutex, thread); +} + +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; +} + +bool __LockMutex(Mutex* mutex) { + // Mutex alread locked? + if (mutex->locked) { + return false; + } + __MutexAcquireLock(mutex); + return true; +} + +bool __ReleaseMutexForThread(Mutex* mutex, Handle thread) { + __MutexAcquireLock(mutex, thread); + Kernel::ResumeThreadFromWait(thread); + return true; +} + +bool __ReleaseMutex(Mutex* mutex) { + __MutexEraseLock(mutex); + bool woke_threads = false; + auto iter = mutex->waiting_threads.begin(); + + // Find the next waiting thread for the mutex... + while (!woke_threads && !mutex->waiting_threads.empty()) { + woke_threads |= __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; +} + +/** + * Releases a mutex + * @param handle Handle to mutex to release + */ +Result ReleaseMutex(Handle handle) { + Mutex* mutex = Kernel::g_object_pool.GetFast(handle); + if (!__ReleaseMutex(mutex)) { + return -1; + } + return 0; +} + +/** + * Creates a mutex + * @param handle Reference to handle for the newly created mutex + * @param initial_locked Specifies if the mutex should be locked initially + */ +Result CreateMutex(Handle& handle, bool initial_locked) { + Mutex* mutex = new Mutex; + handle = Kernel::g_object_pool.Create(mutex); + + mutex->locked = mutex->initial_locked = initial_locked; + + // Acquire mutex with current thread if initialized as locked... + if (mutex->locked) { + __MutexAcquireLock(mutex); + + // Otherwise, reset lock thread handle + } else { + mutex->lock_thread = -1; + } + return 0; +} + +} // namespace -- cgit v1.2.3 From eb537c560a33db9955413a96afd3b98203a729fe Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 23:23:58 -0400 Subject: mutex: refactored the interface to code to return a Mutex* handle --- src/core/hle/kernel/mutex.cpp | 14 ++++++++++++-- 1 file changed, 12 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 2b2cff4ea..7cf3439e9 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -102,7 +102,7 @@ Result ReleaseMutex(Handle handle) { * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially */ -Result CreateMutex(Handle& handle, bool initial_locked) { +Mutex* CreateMutex(Handle& handle, bool initial_locked) { Mutex* mutex = new Mutex; handle = Kernel::g_object_pool.Create(mutex); @@ -116,7 +116,17 @@ Result CreateMutex(Handle& handle, bool initial_locked) { } else { mutex->lock_thread = -1; } - return 0; + return mutex; +} + +/** + * Creates a mutex + * @param initial_locked Specifies if the mutex should be locked initially + */ +Handle CreateMutex(bool initial_locked) { + Handle handle; + Mutex* mutex = CreateMutex(handle, initial_locked); + return handle; } } // namespace -- cgit v1.2.3 From d26f3d4c1ff27f740fe7185e1bca7dcfc5851919 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 May 2014 19:06:12 -0400 Subject: kernel: refactored function naming to remove "__" prefix --- src/core/hle/kernel/mutex.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 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 7cf3439e9..019efbc78 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -30,17 +30,17 @@ public: typedef std::multimap MutexMap; static MutexMap g_mutex_held_locks; -void __MutexAcquireLock(Mutex* mutex, Handle thread) { +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 = GetCurrentThread(); - __MutexAcquireLock(mutex, thread); +void MutexAcquireLock(Mutex* mutex) { + Handle thread = GetCurrentThreadHandle(); + MutexAcquireLock(mutex, thread); } -void __MutexEraseLock(Mutex* mutex) { +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) { @@ -52,29 +52,29 @@ void __MutexEraseLock(Mutex* mutex) { mutex->lock_thread = -1; } -bool __LockMutex(Mutex* mutex) { +bool LockMutex(Mutex* mutex) { // Mutex alread locked? if (mutex->locked) { return false; } - __MutexAcquireLock(mutex); + MutexAcquireLock(mutex); return true; } -bool __ReleaseMutexForThread(Mutex* mutex, Handle thread) { - __MutexAcquireLock(mutex, thread); +bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { + MutexAcquireLock(mutex, thread); Kernel::ResumeThreadFromWait(thread); return true; } -bool __ReleaseMutex(Mutex* mutex) { - __MutexEraseLock(mutex); +bool ReleaseMutex(Mutex* mutex) { + MutexEraseLock(mutex); bool woke_threads = false; auto iter = mutex->waiting_threads.begin(); // Find the next waiting thread for the mutex... while (!woke_threads && !mutex->waiting_threads.empty()) { - woke_threads |= __ReleaseMutexForThread(mutex, *iter); + woke_threads |= ReleaseMutexForThread(mutex, *iter); mutex->waiting_threads.erase(iter); } // Reset mutex lock thread handle, nothing is waiting @@ -91,7 +91,7 @@ bool __ReleaseMutex(Mutex* mutex) { */ Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); - if (!__ReleaseMutex(mutex)) { + if (!ReleaseMutex(mutex)) { return -1; } return 0; @@ -110,7 +110,7 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked) { // Acquire mutex with current thread if initialized as locked... if (mutex->locked) { - __MutexAcquireLock(mutex); + MutexAcquireLock(mutex); // Otherwise, reset lock thread handle } else { -- cgit v1.2.3