From e3c8e4901c51e2ba172f0e1cec0a07dd56f25311 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Fri, 5 Dec 2014 23:40:43 -0500
Subject: [PATCH] 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(-)

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<Handle> waiting_threads;        ///< Threads that are waiting for the mutex
     std::string name;                           ///< Name of mutex (optional)
 
-    ResultVal<bool> SyncRequest() override {
-        // TODO(bunnei): ImplementMe
-        locked = true;
-        return MakeResult<bool>(false);
-    }
-
     ResultVal<bool> 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<bool>(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<Handle>::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;
 }