summaryrefslogtreecommitdiff
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.cpp41
1 files changed, 14 insertions, 27 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index acf484659..9f7166ca4 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -5,6 +5,8 @@
5#include <map> 5#include <map>
6#include <vector> 6#include <vector>
7 7
8#include <boost/range/algorithm_ext/erase.hpp>
9
8#include "common/common.h" 10#include "common/common.h"
9 11
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
@@ -13,9 +15,6 @@
13 15
14namespace Kernel { 16namespace Kernel {
15 17
16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
17static MutexMap g_mutex_held_locks;
18
19/** 18/**
20 * Resumes a thread waiting for the specified mutex 19 * Resumes a thread waiting for the specified mutex
21 * @param mutex The mutex that some thread is waiting on 20 * @param mutex The mutex that some thread is waiting on
@@ -33,21 +32,17 @@ static void ResumeWaitingThread(Mutex* mutex) {
33} 32}
34 33
35void ReleaseThreadMutexes(Thread* thread) { 34void ReleaseThreadMutexes(Thread* thread) {
36 auto locked_range = g_mutex_held_locks.equal_range(thread); 35 for (auto& mtx : thread->held_mutexes) {
37 36 ResumeWaitingThread(mtx.get());
38 // Release every mutex that the thread holds, and resume execution on the waiting threads
39 for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
40 ResumeWaitingThread(iter->second.get());
41 } 37 }
42 38 thread->held_mutexes.clear();
43 // Erase all the locks that this thread holds
44 g_mutex_held_locks.erase(thread);
45} 39}
46 40
47ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { 41Mutex::Mutex() {}
42Mutex::~Mutex() {}
43
44SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
48 SharedPtr<Mutex> mutex(new Mutex); 45 SharedPtr<Mutex> mutex(new Mutex);
49 // TOOD(yuriks): Don't create Handle (see Thread::Create())
50 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
51 46
52 mutex->initial_locked = initial_locked; 47 mutex->initial_locked = initial_locked;
53 mutex->locked = false; 48 mutex->locked = false;
@@ -58,7 +53,7 @@ ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name)
58 if (initial_locked) 53 if (initial_locked)
59 mutex->Acquire(); 54 mutex->Acquire();
60 55
61 return MakeResult<SharedPtr<Mutex>>(mutex); 56 return mutex;
62} 57}
63 58
64bool Mutex::ShouldWait() { 59bool Mutex::ShouldWait() {
@@ -69,30 +64,22 @@ void Mutex::Acquire() {
69 Acquire(GetCurrentThread()); 64 Acquire(GetCurrentThread());
70} 65}
71 66
72void Mutex::Acquire(Thread* thread) { 67void Mutex::Acquire(SharedPtr<Thread> thread) {
73 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 68 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
74 if (locked) 69 if (locked)
75 return; 70 return;
76 71
77 locked = true; 72 locked = true;
78 73
79 g_mutex_held_locks.insert(std::make_pair(thread, this)); 74 thread->held_mutexes.insert(this);
80 holding_thread = thread; 75 holding_thread = std::move(thread);
81} 76}
82 77
83void Mutex::Release() { 78void Mutex::Release() {
84 if (!locked) 79 if (!locked)
85 return; 80 return;
86 81
87 auto locked_range = g_mutex_held_locks.equal_range(holding_thread); 82 holding_thread->held_mutexes.erase(this);
88
89 for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
90 if (iter->second == this) {
91 g_mutex_held_locks.erase(iter);
92 break;
93 }
94 }
95
96 ResumeWaitingThread(this); 83 ResumeWaitingThread(this);
97} 84}
98 85