|
|
|
@ -1677,18 +1677,20 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var |
|
|
|
|
|
|
|
// Atomically read the value of the mutex.
|
|
|
|
u32 mutex_val = 0; |
|
|
|
u32 update_val = 0; |
|
|
|
const VAddr mutex_address = thread->GetMutexWaitAddress(); |
|
|
|
do { |
|
|
|
monitor.SetExclusive(current_core, thread->GetMutexWaitAddress()); |
|
|
|
monitor.SetExclusive(current_core, mutex_address); |
|
|
|
|
|
|
|
// If the mutex is not yet acquired, acquire it.
|
|
|
|
mutex_val = Memory::Read32(thread->GetMutexWaitAddress()); |
|
|
|
mutex_val = Memory::Read32(mutex_address); |
|
|
|
|
|
|
|
if (mutex_val != 0) { |
|
|
|
monitor.ClearExclusive(); |
|
|
|
break; |
|
|
|
update_val = mutex_val | Mutex::MutexHasWaitersFlag; |
|
|
|
} else { |
|
|
|
update_val = thread->GetWaitHandle(); |
|
|
|
} |
|
|
|
} while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), |
|
|
|
thread->GetWaitHandle())); |
|
|
|
} while (!monitor.ExclusiveWrite32(current_core, mutex_address, update_val)); |
|
|
|
if (mutex_val == 0) { |
|
|
|
// We were able to acquire the mutex, resume this thread.
|
|
|
|
ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); |
|
|
|
@ -1702,20 +1704,9 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var |
|
|
|
thread->SetLockOwner(nullptr); |
|
|
|
thread->SetMutexWaitAddress(0); |
|
|
|
thread->SetWaitHandle(0); |
|
|
|
thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
|
|
|
system.PrepareReschedule(thread->GetProcessorID()); |
|
|
|
} else { |
|
|
|
// Atomically signal that the mutex now has a waiting thread.
|
|
|
|
do { |
|
|
|
monitor.SetExclusive(current_core, thread->GetMutexWaitAddress()); |
|
|
|
|
|
|
|
// Ensure that the mutex value is still what we expect.
|
|
|
|
u32 value = Memory::Read32(thread->GetMutexWaitAddress()); |
|
|
|
// TODO(Subv): When this happens, the kernel just clears the exclusive state and
|
|
|
|
// retries the initial read for this thread.
|
|
|
|
ASSERT_MSG(mutex_val == value, "Unhandled synchronization primitive case"); |
|
|
|
} while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), |
|
|
|
mutex_val | Mutex::MutexHasWaitersFlag)); |
|
|
|
|
|
|
|
// The mutex is already owned by some other thread, make this thread wait on it.
|
|
|
|
const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); |
|
|
|
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
|
|
|
|