diff options
| author | bunnei <bunneidev@gmail.com> | 2015-02-09 22:06:09 -0500 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2015-02-09 22:06:09 -0500 | 
| commit | 1b0bf00cbcadfc4cca0a3d16efac8b85a4bd71e5 (patch) | |
| tree | cf72fdea8a5f5e40c0ee07a8b7d705966a19a58a /src/core/hle | |
| parent | caa58acc840efd6881e7816ad4fdb5d48c17e2e2 (diff) | |
Mutex: Locks should be recursive.
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 33 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.h | 3 | 
2 files changed, 20 insertions, 16 deletions
| diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 9f7166ca4..a811db392 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -21,7 +21,7 @@ namespace Kernel {   */  static void ResumeWaitingThread(Mutex* mutex) {      // Reset mutex lock thread handle, nothing is waiting -    mutex->locked = false; +    mutex->lock_count = 0;      mutex->holding_thread = nullptr;      // Find the next waiting thread for the mutex... @@ -44,8 +44,7 @@ Mutex::~Mutex() {}  SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {      SharedPtr<Mutex> mutex(new Mutex); -    mutex->initial_locked = initial_locked; -    mutex->locked = false; +    mutex->lock_count = 0;      mutex->name = std::move(name);      mutex->holding_thread = nullptr; @@ -57,7 +56,7 @@ SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {  }  bool Mutex::ShouldWait() { -    return locked && holding_thread != GetCurrentThread(); +    return lock_count > 0 && holding_thread != GetCurrentThread();;  }  void Mutex::Acquire() { @@ -66,21 +65,27 @@ void Mutex::Acquire() {  void Mutex::Acquire(SharedPtr<Thread> thread) {      _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); -    if (locked) -        return; -    locked = true; +    // Actually "acquire" the mutex only if we don't already have it... +    if (lock_count == 0) { +        thread->held_mutexes.insert(this); +        holding_thread = std::move(thread); +    } -    thread->held_mutexes.insert(this); -    holding_thread = std::move(thread); +    lock_count++;  }  void Mutex::Release() { -    if (!locked) -        return; - -    holding_thread->held_mutexes.erase(this); -    ResumeWaitingThread(this); +    // Only release if the mutex is held... +    if (lock_count > 0) { +        lock_count--; + +        // Yield to the next thread only if we've fully released the mutex... +        if (lock_count == 0) { +            holding_thread->held_mutexes.erase(this); +            ResumeWaitingThread(this); +        } +    }  }  } // namespace diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 548403614..d6d5328be 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -30,8 +30,7 @@ public:      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 +    int lock_count;                             ///< Number of times the mutex has been acquired      std::string name;                           ///< Name of mutex (optional)      SharedPtr<Thread> holding_thread;           ///< Thread that has acquired the mutex | 
