summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/mutex.cpp
diff options
context:
space:
mode:
authorGravatar darkf2014-12-29 19:47:41 -0800
committerGravatar darkf2014-12-29 19:47:41 -0800
commit8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch)
treef1c7c3393fa726435b5b90bf335567c93e528ef1 /src/core/hle/kernel/mutex.cpp
parentAdd comment regarding __WIN32__ in SkyEye code (diff)
parentMerge pull request #367 from bunnei/usat_ssat (diff)
downloadyuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip
Fix merge conflicts
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
-rw-r--r--src/core/hle/kernel/mutex.cpp108
1 files changed, 64 insertions, 44 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index b303ba128..558068c79 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
@@ -18,8 +18,8 @@ public:
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; }
20 20
21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } 21 static const HandleType HANDLE_TYPE = HandleType::Mutex;
22 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Mutex; } 22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
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
@@ -27,21 +27,7 @@ public:
27 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex 27 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex
28 std::string name; ///< Name of mutex (optional) 28 std::string name; ///< Name of mutex (optional)
29 29
30 ResultVal<bool> SyncRequest() override { 30 ResultVal<bool> WaitSynchronization() override;
31 // TODO(bunnei): ImplementMe
32 locked = true;
33 return MakeResult<bool>(false);
34 }
35
36 ResultVal<bool> WaitSynchronization() override {
37 // TODO(bunnei): ImplementMe
38 bool wait = locked;
39 if (locked) {
40 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle());
41 }
42
43 return MakeResult<bool>(wait);
44 }
45}; 31};
46 32
47//////////////////////////////////////////////////////////////////////////////////////////////////// 33////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -49,21 +35,46 @@ public:
49typedef std::multimap<Handle, Handle> MutexMap; 35typedef std::multimap<Handle, Handle> MutexMap;
50static MutexMap g_mutex_held_locks; 36static MutexMap g_mutex_held_locks;
51 37
52void MutexAcquireLock(Mutex* mutex, Handle thread) { 38/**
39 * Acquires the specified mutex for the specified thread
40 * @param mutex Mutex that is to be acquired
41 * @param thread Thread that will acquired
42 */
43void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThreadHandle()) {
53 g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); 44 g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle()));
54 mutex->lock_thread = thread; 45 mutex->lock_thread = thread;
55} 46}
56 47
57void MutexAcquireLock(Mutex* mutex) { 48bool ReleaseMutexForThread(Mutex* mutex, Handle thread) {
58 Handle thread = GetCurrentThreadHandle();
59 MutexAcquireLock(mutex, thread); 49 MutexAcquireLock(mutex, thread);
50 Kernel::ResumeThreadFromWait(thread);
51 return true;
52}
53
54/**
55 * Resumes a thread waiting for the specified mutex
56 * @param mutex The mutex that some thread is waiting on
57 */
58void ResumeWaitingThread(Mutex* mutex) {
59 // Find the next waiting thread for the mutex...
60 if (mutex->waiting_threads.empty()) {
61 // Reset mutex lock thread handle, nothing is waiting
62 mutex->locked = false;
63 mutex->lock_thread = -1;
64 }
65 else {
66 // Resume the next waiting thread and re-lock the mutex
67 std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
68 ReleaseMutexForThread(mutex, *iter);
69 mutex->waiting_threads.erase(iter);
70 }
60} 71}
61 72
62void MutexEraseLock(Mutex* mutex) { 73void MutexEraseLock(Mutex* mutex) {
63 Handle handle = mutex->GetHandle(); 74 Handle handle = mutex->GetHandle();
64 auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread); 75 auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread);
65 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { 76 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
66 if ((*iter).second == handle) { 77 if (iter->second == handle) {
67 g_mutex_held_locks.erase(iter); 78 g_mutex_held_locks.erase(iter);
68 break; 79 break;
69 } 80 }
@@ -71,6 +82,19 @@ void MutexEraseLock(Mutex* mutex) {
71 mutex->lock_thread = -1; 82 mutex->lock_thread = -1;
72} 83}
73 84
85void ReleaseThreadMutexes(Handle thread) {
86 auto locked = g_mutex_held_locks.equal_range(thread);
87
88 // Release every mutex that the thread holds, and resume execution on the waiting threads
89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
90 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second);
91 ResumeWaitingThread(mutex);
92 }
93
94 // Erase all the locks that this thread holds
95 g_mutex_held_locks.erase(thread);
96}
97
74bool LockMutex(Mutex* mutex) { 98bool LockMutex(Mutex* mutex) {
75 // Mutex alread locked? 99 // Mutex alread locked?
76 if (mutex->locked) { 100 if (mutex->locked) {
@@ -80,28 +104,10 @@ bool LockMutex(Mutex* mutex) {
80 return true; 104 return true;
81} 105}
82 106
83bool ReleaseMutexForThread(Mutex* mutex, Handle thread) {
84 MutexAcquireLock(mutex, thread);
85 Kernel::ResumeThreadFromWait(thread);
86 return true;
87}
88
89bool ReleaseMutex(Mutex* mutex) { 107bool ReleaseMutex(Mutex* mutex) {
90 MutexEraseLock(mutex); 108 MutexEraseLock(mutex);
91 bool woke_threads = false; 109 ResumeWaitingThread(mutex);
92 110 return true;
93 // Find the next waiting thread for the mutex...
94 while (!woke_threads && !mutex->waiting_threads.empty()) {
95 std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
96 woke_threads |= ReleaseMutexForThread(mutex, *iter);
97 mutex->waiting_threads.erase(iter);
98 }
99 // Reset mutex lock thread handle, nothing is waiting
100 if (!woke_threads) {
101 mutex->locked = false;
102 mutex->lock_thread = -1;
103 }
104 return woke_threads;
105} 111}
106 112
107/** 113/**
@@ -109,7 +115,7 @@ bool ReleaseMutex(Mutex* mutex) {
109 * @param handle Handle to mutex to release 115 * @param handle Handle to mutex to release
110 */ 116 */
111ResultCode ReleaseMutex(Handle handle) { 117ResultCode ReleaseMutex(Handle handle) {
112 Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle); 118 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle);
113 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); 119 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
114 120
115 if (!ReleaseMutex(mutex)) { 121 if (!ReleaseMutex(mutex)) {
@@ -130,7 +136,8 @@ ResultCode ReleaseMutex(Handle handle) {
130 */ 136 */
131Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { 137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
132 Mutex* mutex = new Mutex; 138 Mutex* mutex = new Mutex;
133 handle = Kernel::g_object_pool.Create(mutex); 139 // TODO(yuriks): Fix error reporting
140 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
134 141
135 mutex->locked = mutex->initial_locked = initial_locked; 142 mutex->locked = mutex->initial_locked = initial_locked;
136 mutex->name = name; 143 mutex->name = name;
@@ -158,4 +165,17 @@ Handle CreateMutex(bool initial_locked, const std::string& name) {
158 return handle; 165 return handle;
159} 166}
160 167
168ResultVal<bool> Mutex::WaitSynchronization() {
169 bool wait = locked;
170 if (locked) {
171 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle());
172 }
173 else {
174 // Lock the mutex when the first thread accesses it
175 locked = true;
176 MutexAcquireLock(this);
177 }
178
179 return MakeResult<bool>(wait);
180}
161} // namespace 181} // namespace