diff options
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 260e25fde..98e87313b 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/hle/kernel/mutex.h" | 13 | #include "core/hle/kernel/mutex.h" |
| 14 | #include "core/hle/kernel/object.h" | 14 | #include "core/hle/kernel/object.h" |
| 15 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/process.h" |
| 16 | #include "core/hle/kernel/scheduler.h" | ||
| 16 | #include "core/hle/kernel/thread.h" | 17 | #include "core/hle/kernel/thread.h" |
| 17 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| 18 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| @@ -69,34 +70,36 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | |||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 72 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 73 | Thread* const current_thread = system.CurrentScheduler().GetCurrentThread(); | ||
| 72 | SharedPtr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); | 74 | SharedPtr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); |
| 73 | SharedPtr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); | 75 | SharedPtr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); |
| 74 | 76 | ||
| 75 | // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another | 77 | // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another |
| 76 | // thread. | 78 | // thread. |
| 77 | ASSERT(requesting_thread == GetCurrentThread()); | 79 | ASSERT(requesting_thread == current_thread); |
| 78 | 80 | ||
| 79 | u32 addr_value = Memory::Read32(address); | 81 | const u32 addr_value = Memory::Read32(address); |
| 80 | 82 | ||
| 81 | // If the mutex isn't being held, just return success. | 83 | // If the mutex isn't being held, just return success. |
| 82 | if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) { | 84 | if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) { |
| 83 | return RESULT_SUCCESS; | 85 | return RESULT_SUCCESS; |
| 84 | } | 86 | } |
| 85 | 87 | ||
| 86 | if (holding_thread == nullptr) | 88 | if (holding_thread == nullptr) { |
| 87 | return ERR_INVALID_HANDLE; | 89 | return ERR_INVALID_HANDLE; |
| 90 | } | ||
| 88 | 91 | ||
| 89 | // Wait until the mutex is released | 92 | // Wait until the mutex is released |
| 90 | GetCurrentThread()->SetMutexWaitAddress(address); | 93 | current_thread->SetMutexWaitAddress(address); |
| 91 | GetCurrentThread()->SetWaitHandle(requesting_thread_handle); | 94 | current_thread->SetWaitHandle(requesting_thread_handle); |
| 92 | 95 | ||
| 93 | GetCurrentThread()->SetStatus(ThreadStatus::WaitMutex); | 96 | current_thread->SetStatus(ThreadStatus::WaitMutex); |
| 94 | GetCurrentThread()->InvalidateWakeupCallback(); | 97 | current_thread->InvalidateWakeupCallback(); |
| 95 | 98 | ||
| 96 | // Update the lock holder thread's priority to prevent priority inversion. | 99 | // Update the lock holder thread's priority to prevent priority inversion. |
| 97 | holding_thread->AddMutexWaiter(GetCurrentThread()); | 100 | holding_thread->AddMutexWaiter(current_thread); |
| 98 | 101 | ||
| 99 | Core::System::GetInstance().PrepareReschedule(); | 102 | system.PrepareReschedule(); |
| 100 | 103 | ||
| 101 | return RESULT_SUCCESS; | 104 | return RESULT_SUCCESS; |
| 102 | } | 105 | } |
| @@ -107,7 +110,8 @@ ResultCode Mutex::Release(VAddr address) { | |||
| 107 | return ERR_INVALID_ADDRESS; | 110 | return ERR_INVALID_ADDRESS; |
| 108 | } | 111 | } |
| 109 | 112 | ||
| 110 | auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); | 113 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); |
| 114 | auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(current_thread, address); | ||
| 111 | 115 | ||
| 112 | // There are no more threads waiting for the mutex, release it completely. | 116 | // There are no more threads waiting for the mutex, release it completely. |
| 113 | if (thread == nullptr) { | 117 | if (thread == nullptr) { |
| @@ -116,7 +120,7 @@ ResultCode Mutex::Release(VAddr address) { | |||
| 116 | } | 120 | } |
| 117 | 121 | ||
| 118 | // Transfer the ownership of the mutex from the previous owner to the new one. | 122 | // Transfer the ownership of the mutex from the previous owner to the new one. |
| 119 | TransferMutexOwnership(address, GetCurrentThread(), thread); | 123 | TransferMutexOwnership(address, current_thread, thread); |
| 120 | 124 | ||
| 121 | u32 mutex_value = thread->GetWaitHandle(); | 125 | u32 mutex_value = thread->GetWaitHandle(); |
| 122 | 126 | ||