diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2020-02-25 21:38:33 +0100 |
---|---|---|
committer | Fernando Sahmkow <fsahmkow27@gmail.com> | 2020-06-27 17:35:13 +0200 |
commit | 3b5b950c895a2db217a3e5c8105cec4498a2534e (patch) | |
tree | 2a8e054af30c9aa8039f8faa4b993e2290642184 /src/core/hle/kernel/mutex.cpp | |
parent | SVC: Remove global HLE Lock. (diff) | |
download | yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.gz yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.bz2 yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.lz yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.xz yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.zst yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.zip |
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
-rw-r--r-- | src/core/hle/kernel/mutex.cpp | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 7869eb32b..3520c5e49 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -72,42 +72,55 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, return ERR_INVALID_ADDRESS; } - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); + auto& kernel = system.Kernel(); std::shared_ptr<Thread> current_thread = - SharedFrom(system.CurrentScheduler().GetCurrentThread()); - std::shared_ptr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); - std::shared_ptr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); + SharedFrom(kernel.CurrentScheduler().GetCurrentThread()); + { + SchedulerLock lock(kernel); + // The mutex address must be 4-byte aligned + if ((address % sizeof(u32)) != 0) { + return ERR_INVALID_ADDRESS; + } - // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another - // thread. - ASSERT(requesting_thread == current_thread); + const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); + std::shared_ptr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); + std::shared_ptr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); - const u32 addr_value = system.Memory().Read32(address); + // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another + // thread. + ASSERT(requesting_thread == current_thread); - // If the mutex isn't being held, just return success. - if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) { - return RESULT_SUCCESS; - } + current_thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); - if (holding_thread == nullptr) { - LOG_ERROR(Kernel, "Holding thread does not exist! thread_handle={:08X}", - holding_thread_handle); - return ERR_INVALID_HANDLE; - } + const u32 addr_value = system.Memory().Read32(address); - // Wait until the mutex is released - current_thread->SetMutexWaitAddress(address); - current_thread->SetWaitHandle(requesting_thread_handle); + // If the mutex isn't being held, just return success. + if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) { + return RESULT_SUCCESS; + } - current_thread->SetStatus(ThreadStatus::WaitMutex); - current_thread->InvalidateWakeupCallback(); + if (holding_thread == nullptr) { + return ERR_INVALID_HANDLE; + } - // Update the lock holder thread's priority to prevent priority inversion. - holding_thread->AddMutexWaiter(current_thread); + // Wait until the mutex is released + current_thread->SetMutexWaitAddress(address); + current_thread->SetWaitHandle(requesting_thread_handle); - system.PrepareReschedule(); + current_thread->SetStatus(ThreadStatus::WaitMutex); - return RESULT_SUCCESS; + // Update the lock holder thread's priority to prevent priority inversion. + holding_thread->AddMutexWaiter(current_thread); + } + + { + SchedulerLock lock(kernel); + auto* owner = current_thread->GetLockOwner(); + if (owner != nullptr) { + owner->RemoveMutexWaiter(current_thread); + } + } + return current_thread->GetSignalingResult(); } ResultCode Mutex::Release(VAddr address) { |