diff options
| author | 2019-10-07 18:57:13 -0400 | |
|---|---|---|
| committer | 2019-10-15 11:55:18 -0400 | |
| commit | 44e09e5f21915391672558940842b92e3a64cb1b (patch) | |
| tree | 3a0e4db9cff1ad0ed7c70d4a6fc91695f8e1c137 /src/core/hle/kernel/svc.cpp | |
| parent | Kernel: Clang Format (diff) | |
| download | yuzu-44e09e5f21915391672558940842b92e3a64cb1b.tar.gz yuzu-44e09e5f21915391672558940842b92e3a64cb1b.tar.xz yuzu-44e09e5f21915391672558940842b92e3a64cb1b.zip | |
Kernel: Correct Results in Condition Variables and Mutexes
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 27 |
1 files changed, 9 insertions, 18 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bd67fc96d..823d1d403 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1677,18 +1677,20 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var | |||
| 1677 | 1677 | ||
| 1678 | // Atomically read the value of the mutex. | 1678 | // Atomically read the value of the mutex. |
| 1679 | u32 mutex_val = 0; | 1679 | u32 mutex_val = 0; |
| 1680 | u32 update_val = 0; | ||
| 1681 | const VAddr mutex_address = thread->GetMutexWaitAddress(); | ||
| 1680 | do { | 1682 | do { |
| 1681 | monitor.SetExclusive(current_core, thread->GetMutexWaitAddress()); | 1683 | monitor.SetExclusive(current_core, mutex_address); |
| 1682 | 1684 | ||
| 1683 | // If the mutex is not yet acquired, acquire it. | 1685 | // If the mutex is not yet acquired, acquire it. |
| 1684 | mutex_val = Memory::Read32(thread->GetMutexWaitAddress()); | 1686 | mutex_val = Memory::Read32(mutex_address); |
| 1685 | 1687 | ||
| 1686 | if (mutex_val != 0) { | 1688 | if (mutex_val != 0) { |
| 1687 | monitor.ClearExclusive(); | 1689 | update_val = mutex_val | Mutex::MutexHasWaitersFlag; |
| 1688 | break; | 1690 | } else { |
| 1691 | update_val = thread->GetWaitHandle(); | ||
| 1689 | } | 1692 | } |
| 1690 | } while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), | 1693 | } while (!monitor.ExclusiveWrite32(current_core, mutex_address, update_val)); |
| 1691 | thread->GetWaitHandle())); | ||
| 1692 | if (mutex_val == 0) { | 1694 | if (mutex_val == 0) { |
| 1693 | // We were able to acquire the mutex, resume this thread. | 1695 | // We were able to acquire the mutex, resume this thread. |
| 1694 | ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); | 1696 | ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); |
| @@ -1702,20 +1704,9 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var | |||
| 1702 | thread->SetLockOwner(nullptr); | 1704 | thread->SetLockOwner(nullptr); |
| 1703 | thread->SetMutexWaitAddress(0); | 1705 | thread->SetMutexWaitAddress(0); |
| 1704 | thread->SetWaitHandle(0); | 1706 | thread->SetWaitHandle(0); |
| 1707 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 1705 | system.PrepareReschedule(thread->GetProcessorID()); | 1708 | system.PrepareReschedule(thread->GetProcessorID()); |
| 1706 | } else { | 1709 | } else { |
| 1707 | // Atomically signal that the mutex now has a waiting thread. | ||
| 1708 | do { | ||
| 1709 | monitor.SetExclusive(current_core, thread->GetMutexWaitAddress()); | ||
| 1710 | |||
| 1711 | // Ensure that the mutex value is still what we expect. | ||
| 1712 | u32 value = Memory::Read32(thread->GetMutexWaitAddress()); | ||
| 1713 | // TODO(Subv): When this happens, the kernel just clears the exclusive state and | ||
| 1714 | // retries the initial read for this thread. | ||
| 1715 | ASSERT_MSG(mutex_val == value, "Unhandled synchronization primitive case"); | ||
| 1716 | } while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), | ||
| 1717 | mutex_val | Mutex::MutexHasWaitersFlag)); | ||
| 1718 | |||
| 1719 | // The mutex is already owned by some other thread, make this thread wait on it. | 1710 | // The mutex is already owned by some other thread, make this thread wait on it. |
| 1720 | const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); | 1711 | const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); |
| 1721 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1712 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |