summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/mutex.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2015-01-21 21:09:47 -0500
committerGravatar bunnei2015-01-21 21:09:47 -0500
commit24a63662ba6c7816001bba399e85d8c131a89489 (patch)
treea9959e69723b4f19550834171c962ec06c9e34b7 /src/core/hle/kernel/mutex.cpp
parentMerge pull request #491 from archshift/hidspvr (diff)
parentWaitSynchronization: Added a result code for invalid result, fixed bug. (diff)
downloadyuzu-24a63662ba6c7816001bba399e85d8c131a89489.tar.gz
yuzu-24a63662ba6c7816001bba399e85d8c131a89489.tar.xz
yuzu-24a63662ba6c7816001bba399e85d8c131a89489.zip
Merge pull request #495 from bunnei/fix-waitsynch
Fix WaitSynchronization
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
-rw-r--r--src/core/hle/kernel/mutex.cpp112
1 files changed, 39 insertions, 73 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 853a5dd74..cd05a1397 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -13,7 +13,7 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16class Mutex : public Object { 16class Mutex : public WaitObject {
17public: 17public:
18 std::string GetTypeName() const override { return "Mutex"; } 18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const override { return name; } 19 std::string GetName() const override { return name; }
@@ -23,39 +23,26 @@ public:
23 23
24 bool initial_locked; ///< Initial lock state when mutex was created 24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state 25 bool locked; ///< Current locked state
26 Handle lock_thread; ///< Handle to thread that currently has mutex
27 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex
28 std::string name; ///< Name of mutex (optional) 26 std::string name; ///< Name of mutex (optional)
27 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
29 28
30 ResultVal<bool> WaitSynchronization() override; 29 bool ShouldWait() override;
30 void Acquire() override;
31}; 31};
32 32
33//////////////////////////////////////////////////////////////////////////////////////////////////// 33////////////////////////////////////////////////////////////////////////////////////////////////////
34 34
35typedef std::multimap<Handle, Handle> MutexMap; 35typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
36static MutexMap g_mutex_held_locks; 36static MutexMap g_mutex_held_locks;
37 37
38/** 38/**
39 * Acquires the specified mutex for the specified thread 39 * Acquires the specified mutex for the specified thread
40 * @param mutex Mutex that is to be acquired 40 * @param mutex Mutex that is to be acquired
41 * @param thread Thread that will acquired 41 * @param thread Thread that will acquire the mutex
42 */ 42 */
43void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandle()) { 43void MutexAcquireLock(Mutex* mutex, Thread* thread) {
44 g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); 44 g_mutex_held_locks.insert(std::make_pair(thread, mutex));
45 mutex->lock_thread = thread; 45 mutex->holding_thread = thread;
46}
47
48bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) {
49 MutexAcquireLock(mutex, thread_handle);
50
51 Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle).get();
52 if (thread == nullptr) {
53 LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle);
54 return false;
55 }
56
57 thread->ResumeFromWait();
58 return true;
59} 46}
60 47
61/** 48/**
@@ -64,56 +51,41 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) {
64 */ 51 */
65void ResumeWaitingThread(Mutex* mutex) { 52void ResumeWaitingThread(Mutex* mutex) {
66 // Find the next waiting thread for the mutex... 53 // Find the next waiting thread for the mutex...
67 if (mutex->waiting_threads.empty()) { 54 auto next_thread = mutex->WakeupNextThread();
55 if (next_thread != nullptr) {
56 MutexAcquireLock(mutex, next_thread);
57 } else {
68 // Reset mutex lock thread handle, nothing is waiting 58 // Reset mutex lock thread handle, nothing is waiting
69 mutex->locked = false; 59 mutex->locked = false;
70 mutex->lock_thread = -1; 60 mutex->holding_thread = nullptr;
71 }
72 else {
73 // Resume the next waiting thread and re-lock the mutex
74 std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
75 ReleaseMutexForThread(mutex, *iter);
76 mutex->waiting_threads.erase(iter);
77 } 61 }
78} 62}
79 63
80void MutexEraseLock(Mutex* mutex) { 64void ReleaseThreadMutexes(Thread* thread) {
81 Handle handle = mutex->GetHandle();
82 auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread);
83 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
84 if (iter->second == handle) {
85 g_mutex_held_locks.erase(iter);
86 break;
87 }
88 }
89 mutex->lock_thread = -1;
90}
91
92void ReleaseThreadMutexes(Handle thread) {
93 auto locked = g_mutex_held_locks.equal_range(thread); 65 auto locked = g_mutex_held_locks.equal_range(thread);
94 66
95 // Release every mutex that the thread holds, and resume execution on the waiting threads 67 // Release every mutex that the thread holds, and resume execution on the waiting threads
96 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { 68 for (auto iter = locked.first; iter != locked.second; ++iter) {
97 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second).get(); 69 ResumeWaitingThread(iter->second.get());
98 ResumeWaitingThread(mutex);
99 } 70 }
100 71
101 // Erase all the locks that this thread holds 72 // Erase all the locks that this thread holds
102 g_mutex_held_locks.erase(thread); 73 g_mutex_held_locks.erase(thread);
103} 74}
104 75
105bool LockMutex(Mutex* mutex) { 76bool ReleaseMutex(Mutex* mutex) {
106 // Mutex alread locked?
107 if (mutex->locked) { 77 if (mutex->locked) {
108 return false; 78 auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread);
109 }
110 MutexAcquireLock(mutex);
111 return true;
112}
113 79
114bool ReleaseMutex(Mutex* mutex) { 80 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
115 MutexEraseLock(mutex); 81 if (iter->second == mutex) {
116 ResumeWaitingThread(mutex); 82 g_mutex_held_locks.erase(iter);
83 break;
84 }
85 }
86
87 ResumeWaitingThread(mutex);
88 }
117 return true; 89 return true;
118} 90}
119 91
@@ -148,15 +120,12 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name)
148 120
149 mutex->locked = mutex->initial_locked = initial_locked; 121 mutex->locked = mutex->initial_locked = initial_locked;
150 mutex->name = name; 122 mutex->name = name;
123 mutex->holding_thread = nullptr;
151 124
152 // Acquire mutex with current thread if initialized as locked... 125 // Acquire mutex with current thread if initialized as locked...
153 if (mutex->locked) { 126 if (mutex->locked)
154 MutexAcquireLock(mutex); 127 MutexAcquireLock(mutex, GetCurrentThread());
155 128
156 // Otherwise, reset lock thread handle
157 } else {
158 mutex->lock_thread = -1;
159 }
160 return mutex; 129 return mutex;
161} 130}
162 131
@@ -172,17 +141,14 @@ Handle CreateMutex(bool initial_locked, const std::string& name) {
172 return handle; 141 return handle;
173} 142}
174 143
175ResultVal<bool> Mutex::WaitSynchronization() { 144bool Mutex::ShouldWait() {
176 bool wait = locked; 145 return locked && holding_thread != GetCurrentThread();
177 if (locked) { 146}
178 waiting_threads.push_back(GetCurrentThread()->GetHandle());
179 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, this);
180 } else {
181 // Lock the mutex when the first thread accesses it
182 locked = true;
183 MutexAcquireLock(this);
184 }
185 147
186 return MakeResult<bool>(wait); 148void Mutex::Acquire() {
149 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
150 locked = true;
151 MutexAcquireLock(this, GetCurrentThread());
187} 152}
153
188} // namespace 154} // namespace