summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/kernel.cpp13
-rw-r--r--src/core/hle/kernel/mutex.cpp1
-rw-r--r--src/core/hle/kernel/svc.cpp27
3 files changed, 17 insertions, 24 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 77edbcd1f..002c5af2b 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -15,6 +15,7 @@
15#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
16#include "core/hle/kernel/address_arbiter.h" 16#include "core/hle/kernel/address_arbiter.h"
17#include "core/hle/kernel/client_port.h" 17#include "core/hle/kernel/client_port.h"
18#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/handle_table.h" 19#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
20#include "core/hle/kernel/process.h" 21#include "core/hle/kernel/process.h"
@@ -60,12 +61,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
60 if (thread->HasWakeupCallback()) { 61 if (thread->HasWakeupCallback()) {
61 resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0); 62 resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
62 } 63 }
63 } 64 } else if (thread->GetStatus() == ThreadStatus::WaitMutex ||
64 65 thread->GetStatus() == ThreadStatus::WaitCondVar) {
65 if (thread->GetMutexWaitAddress() != 0 || thread->GetCondVarWaitAddress() != 0 ||
66 thread->GetWaitHandle() != 0) {
67 ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex ||
68 thread->GetStatus() == ThreadStatus::WaitCondVar);
69 thread->SetMutexWaitAddress(0); 66 thread->SetMutexWaitAddress(0);
70 thread->SetCondVarWaitAddress(0); 67 thread->SetCondVarWaitAddress(0);
71 thread->SetWaitHandle(0); 68 thread->SetWaitHandle(0);
@@ -85,6 +82,10 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
85 } 82 }
86 83
87 if (resume) { 84 if (resume) {
85 if (thread->GetStatus() == ThreadStatus::WaitCondVar ||
86 thread->GetStatus() == ThreadStatus::WaitArb) {
87 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
88 }
88 thread->ResumeFromWait(); 89 thread->ResumeFromWait();
89 } 90 }
90} 91}
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index eb919246c..663d0f4b6 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -139,6 +139,7 @@ ResultCode Mutex::Release(VAddr address) {
139 thread->SetCondVarWaitAddress(0); 139 thread->SetCondVarWaitAddress(0);
140 thread->SetMutexWaitAddress(0); 140 thread->SetMutexWaitAddress(0);
141 thread->SetWaitHandle(0); 141 thread->SetWaitHandle(0);
142 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
142 143
143 system.PrepareReschedule(); 144 system.PrepareReschedule();
144 145
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();