summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/mutex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
-rw-r--r--src/core/hle/kernel/mutex.cpp131
1 files changed, 43 insertions, 88 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index c94c2acc9..acf484659 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -13,59 +13,30 @@
namespace Kernel {
-class Mutex : public WaitObject {
-public:
- std::string GetTypeName() const override { return "Mutex"; }
- std::string GetName() const override { return name; }
-
- 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
- std::string name; ///< Name of mutex (optional)
- SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
-
- bool ShouldWait() override;
- void Acquire() override;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> 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 acquire the mutex
- */
-static void MutexAcquireLock(Mutex* mutex, Thread* thread) {
- g_mutex_held_locks.insert(std::make_pair(thread, mutex));
- mutex->holding_thread = thread;
-}
-
-/**
* Resumes a thread waiting for the specified mutex
* @param mutex The mutex that some thread is waiting on
*/
static void ResumeWaitingThread(Mutex* mutex) {
+ // Reset mutex lock thread handle, nothing is waiting
+ mutex->locked = false;
+ mutex->holding_thread = nullptr;
+
// Find the next waiting thread for the mutex...
auto next_thread = mutex->WakeupNextThread();
if (next_thread != nullptr) {
- MutexAcquireLock(mutex, next_thread);
- } else {
- // Reset mutex lock thread handle, nothing is waiting
- mutex->locked = false;
- mutex->holding_thread = nullptr;
+ mutex->Acquire(next_thread);
}
}
void ReleaseThreadMutexes(Thread* thread) {
- auto locked = g_mutex_held_locks.equal_range(thread);
+ auto locked_range = g_mutex_held_locks.equal_range(thread);
// Release every mutex that the thread holds, and resume execution on the waiting threads
- for (auto iter = locked.first; iter != locked.second; ++iter) {
+ for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
ResumeWaitingThread(iter->second.get());
}
@@ -73,62 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) {
g_mutex_held_locks.erase(thread);
}
-static bool ReleaseMutex(Mutex* mutex) {
- if (mutex->locked) {
- auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread);
-
- 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;
-}
-
-ResultCode ReleaseMutex(Handle handle) {
- Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get();
- if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
-
- if (!ReleaseMutex(mutex)) {
- // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
- // what error condition this is supposed to be signaling.
- return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
- ErrorSummary::NothingHappened, ErrorLevel::Temporary);
- }
- return RESULT_SUCCESS;
-}
-
-/**
- * Creates a mutex
- * @param handle Reference to handle for the newly created mutex
- * @param initial_locked Specifies if the mutex should be locked initially
- * @param name Optional name of mutex
- * @return Pointer to new Mutex object
- */
-static Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
- Mutex* mutex = new Mutex;
- // TODO(yuriks): Fix error reporting
- handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
+ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) {
+ SharedPtr<Mutex> mutex(new Mutex);
+ // TOOD(yuriks): Don't create Handle (see Thread::Create())
+ CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
- mutex->locked = mutex->initial_locked = initial_locked;
- mutex->name = name;
+ mutex->initial_locked = initial_locked;
+ mutex->locked = false;
+ mutex->name = std::move(name);
mutex->holding_thread = nullptr;
// Acquire mutex with current thread if initialized as locked...
- if (mutex->locked)
- MutexAcquireLock(mutex, GetCurrentThread());
+ if (initial_locked)
+ mutex->Acquire();
- return mutex;
-}
-
-Handle CreateMutex(bool initial_locked, const std::string& name) {
- Handle handle;
- Mutex* mutex = CreateMutex(handle, initial_locked, name);
- return handle;
+ return MakeResult<SharedPtr<Mutex>>(mutex);
}
bool Mutex::ShouldWait() {
@@ -136,9 +66,34 @@ bool Mutex::ShouldWait() {
}
void Mutex::Acquire() {
+ Acquire(GetCurrentThread());
+}
+
+void Mutex::Acquire(Thread* thread) {
_assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
+ if (locked)
+ return;
+
locked = true;
- MutexAcquireLock(this, GetCurrentThread());
+
+ g_mutex_held_locks.insert(std::make_pair(thread, this));
+ holding_thread = thread;
+}
+
+void Mutex::Release() {
+ if (!locked)
+ return;
+
+ auto locked_range = g_mutex_held_locks.equal_range(holding_thread);
+
+ for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
+ if (iter->second == this) {
+ g_mutex_held_locks.erase(iter);
+ break;
+ }
+ }
+
+ ResumeWaitingThread(this);
}
} // namespace