summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/mutex.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-01-22 23:12:19 -0200
committerGravatar Yuri Kunde Schlesner2015-01-30 11:47:06 -0200
commit882b6fed75b7bf34809493482496e98c498a14e0 (patch)
tree7d44259e18b47559774f1d7e159fbd0c235d0318 /src/core/hle/kernel/mutex.cpp
parentKernel: Convert AddressArbiter to not use Handles (diff)
downloadyuzu-882b6fed75b7bf34809493482496e98c498a14e0.tar.gz
yuzu-882b6fed75b7bf34809493482496e98c498a14e0.tar.xz
yuzu-882b6fed75b7bf34809493482496e98c498a14e0.zip
Kernel: Convert Mutex to not use Handles
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
-rw-r--r--src/core/hle/kernel/mutex.cpp131
1 files changed, 43 insertions, 88 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index c94c2acc9..acf484659 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -13,59 +13,30 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16class Mutex : public WaitObject {
17public:
18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const override { return name; }
20
21 static const HandleType HANDLE_TYPE = HandleType::Mutex;
22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23
24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state
26 std::string name; ///< Name of mutex (optional)
27 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
28
29 bool ShouldWait() override;
30 void Acquire() override;
31};
32
33////////////////////////////////////////////////////////////////////////////////////////////////////
34
35typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; 16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
36static MutexMap g_mutex_held_locks; 17static MutexMap g_mutex_held_locks;
37 18
38/** 19/**
39 * Acquires the specified mutex for the specified thread
40 * @param mutex Mutex that is to be acquired
41 * @param thread Thread that will acquire the mutex
42 */
43static void MutexAcquireLock(Mutex* mutex, Thread* thread) {
44 g_mutex_held_locks.insert(std::make_pair(thread, mutex));
45 mutex->holding_thread = thread;
46}
47
48/**
49 * Resumes a thread waiting for the specified mutex 20 * Resumes a thread waiting for the specified mutex
50 * @param mutex The mutex that some thread is waiting on 21 * @param mutex The mutex that some thread is waiting on
51 */ 22 */
52static void ResumeWaitingThread(Mutex* mutex) { 23static void ResumeWaitingThread(Mutex* mutex) {
24 // Reset mutex lock thread handle, nothing is waiting
25 mutex->locked = false;
26 mutex->holding_thread = nullptr;
27
53 // Find the next waiting thread for the mutex... 28 // Find the next waiting thread for the mutex...
54 auto next_thread = mutex->WakeupNextThread(); 29 auto next_thread = mutex->WakeupNextThread();
55 if (next_thread != nullptr) { 30 if (next_thread != nullptr) {
56 MutexAcquireLock(mutex, next_thread); 31 mutex->Acquire(next_thread);
57 } else {
58 // Reset mutex lock thread handle, nothing is waiting
59 mutex->locked = false;
60 mutex->holding_thread = nullptr;
61 } 32 }
62} 33}
63 34
64void ReleaseThreadMutexes(Thread* thread) { 35void ReleaseThreadMutexes(Thread* thread) {
65 auto locked = g_mutex_held_locks.equal_range(thread); 36 auto locked_range = g_mutex_held_locks.equal_range(thread);
66 37
67 // Release every mutex that the thread holds, and resume execution on the waiting threads 38 // Release every mutex that the thread holds, and resume execution on the waiting threads
68 for (auto iter = locked.first; iter != locked.second; ++iter) { 39 for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
69 ResumeWaitingThread(iter->second.get()); 40 ResumeWaitingThread(iter->second.get());
70 } 41 }
71 42
@@ -73,62 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) {
73 g_mutex_held_locks.erase(thread); 44 g_mutex_held_locks.erase(thread);
74} 45}
75 46
76static bool ReleaseMutex(Mutex* mutex) { 47ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) {
77 if (mutex->locked) { 48 SharedPtr<Mutex> mutex(new Mutex);
78 auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); 49 // TOOD(yuriks): Don't create Handle (see Thread::Create())
79 50 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
80 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
81 if (iter->second == mutex) {
82 g_mutex_held_locks.erase(iter);
83 break;
84 }
85 }
86
87 ResumeWaitingThread(mutex);
88 }
89 return true;
90}
91
92ResultCode ReleaseMutex(Handle handle) {
93 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get();
94 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
95
96 if (!ReleaseMutex(mutex)) {
97 // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
98 // what error condition this is supposed to be signaling.
99 return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
100 ErrorSummary::NothingHappened, ErrorLevel::Temporary);
101 }
102 return RESULT_SUCCESS;
103}
104
105/**
106 * Creates a mutex
107 * @param handle Reference to handle for the newly created mutex
108 * @param initial_locked Specifies if the mutex should be locked initially
109 * @param name Optional name of mutex
110 * @return Pointer to new Mutex object
111 */
112static Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
113 Mutex* mutex = new Mutex;
114 // TODO(yuriks): Fix error reporting
115 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
116 51
117 mutex->locked = mutex->initial_locked = initial_locked; 52 mutex->initial_locked = initial_locked;
118 mutex->name = name; 53 mutex->locked = false;
54 mutex->name = std::move(name);
119 mutex->holding_thread = nullptr; 55 mutex->holding_thread = nullptr;
120 56
121 // Acquire mutex with current thread if initialized as locked... 57 // Acquire mutex with current thread if initialized as locked...
122 if (mutex->locked) 58 if (initial_locked)
123 MutexAcquireLock(mutex, GetCurrentThread()); 59 mutex->Acquire();
124 60
125 return mutex; 61 return MakeResult<SharedPtr<Mutex>>(mutex);
126}
127
128Handle CreateMutex(bool initial_locked, const std::string& name) {
129 Handle handle;
130 Mutex* mutex = CreateMutex(handle, initial_locked, name);
131 return handle;
132} 62}
133 63
134bool Mutex::ShouldWait() { 64bool Mutex::ShouldWait() {
@@ -136,9 +66,34 @@ bool Mutex::ShouldWait() {
136} 66}
137 67
138void Mutex::Acquire() { 68void Mutex::Acquire() {
69 Acquire(GetCurrentThread());
70}
71
72void Mutex::Acquire(Thread* thread) {
139 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 73 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
74 if (locked)
75 return;
76
140 locked = true; 77 locked = true;
141 MutexAcquireLock(this, GetCurrentThread()); 78
79 g_mutex_held_locks.insert(std::make_pair(thread, this));
80 holding_thread = thread;
81}
82
83void Mutex::Release() {
84 if (!locked)
85 return;
86
87 auto locked_range = g_mutex_held_locks.equal_range(holding_thread);
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);
142} 97}
143 98
144} // namespace 99} // namespace