summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/mutex.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-25 16:38:33 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:13 -0400
commit3b5b950c895a2db217a3e5c8105cec4498a2534e (patch)
tree2a8e054af30c9aa8039f8faa4b993e2290642184 /src/core/hle/kernel/mutex.cpp
parentSVC: Remove global HLE Lock. (diff)
downloadyuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.gz
yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.tar.xz
yuzu-3b5b950c895a2db217a3e5c8105cec4498a2534e.zip
SVC: Correct SignalEvent, ClearEvent, ResetSignal, WaitSynchronization, CancelSynchronization, ArbitrateLock
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
-rw-r--r--src/core/hle/kernel/mutex.cpp65
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,
72 return ERR_INVALID_ADDRESS; 72 return ERR_INVALID_ADDRESS;
73 } 73 }
74 74
75 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 75 auto& kernel = system.Kernel();
76 std::shared_ptr<Thread> current_thread = 76 std::shared_ptr<Thread> current_thread =
77 SharedFrom(system.CurrentScheduler().GetCurrentThread()); 77 SharedFrom(kernel.CurrentScheduler().GetCurrentThread());
78 std::shared_ptr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); 78 {
79 std::shared_ptr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle); 79 SchedulerLock lock(kernel);
80 // The mutex address must be 4-byte aligned
81 if ((address % sizeof(u32)) != 0) {
82 return ERR_INVALID_ADDRESS;
83 }
80 84
81 // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another 85 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
82 // thread. 86 std::shared_ptr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle);
83 ASSERT(requesting_thread == current_thread); 87 std::shared_ptr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle);
84 88
85 const u32 addr_value = system.Memory().Read32(address); 89 // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another
90 // thread.
91 ASSERT(requesting_thread == current_thread);
86 92
87 // If the mutex isn't being held, just return success. 93 current_thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
88 if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) {
89 return RESULT_SUCCESS;
90 }
91 94
92 if (holding_thread == nullptr) { 95 const u32 addr_value = system.Memory().Read32(address);
93 LOG_ERROR(Kernel, "Holding thread does not exist! thread_handle={:08X}",
94 holding_thread_handle);
95 return ERR_INVALID_HANDLE;
96 }
97 96
98 // Wait until the mutex is released 97 // If the mutex isn't being held, just return success.
99 current_thread->SetMutexWaitAddress(address); 98 if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) {
100 current_thread->SetWaitHandle(requesting_thread_handle); 99 return RESULT_SUCCESS;
100 }
101 101
102 current_thread->SetStatus(ThreadStatus::WaitMutex); 102 if (holding_thread == nullptr) {
103 current_thread->InvalidateWakeupCallback(); 103 return ERR_INVALID_HANDLE;
104 }
104 105
105 // Update the lock holder thread's priority to prevent priority inversion. 106 // Wait until the mutex is released
106 holding_thread->AddMutexWaiter(current_thread); 107 current_thread->SetMutexWaitAddress(address);
108 current_thread->SetWaitHandle(requesting_thread_handle);
107 109
108 system.PrepareReschedule(); 110 current_thread->SetStatus(ThreadStatus::WaitMutex);
109 111
110 return RESULT_SUCCESS; 112 // Update the lock holder thread's priority to prevent priority inversion.
113 holding_thread->AddMutexWaiter(current_thread);
114 }
115
116 {
117 SchedulerLock lock(kernel);
118 auto* owner = current_thread->GetLockOwner();
119 if (owner != nullptr) {
120 owner->RemoveMutexWaiter(current_thread);
121 }
122 }
123 return current_thread->GetSignalingResult();
111} 124}
112 125
113ResultCode Mutex::Release(VAddr address) { 126ResultCode Mutex::Release(VAddr address) {