summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp25
-rw-r--r--src/core/hle/kernel/thread.cpp2
2 files changed, 18 insertions, 9 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 195286422..5c3c47acf 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -45,30 +45,32 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
45 45
46 // Wait current thread (acquire the arbiter)... 46 // Wait current thread (acquire the arbiter)...
47 case ArbitrationType::WaitIfLessThan: 47 case ArbitrationType::WaitIfLessThan:
48 if ((s32)Memory::Read32(address) <= value) { 48 if ((s32)Memory::Read32(address) < value) {
49 Kernel::WaitCurrentThread_ArbitrateAddress(address); 49 Kernel::WaitCurrentThread_ArbitrateAddress(address);
50 } 50 }
51 break; 51 break;
52 case ArbitrationType::WaitIfLessThanWithTimeout: 52 case ArbitrationType::WaitIfLessThanWithTimeout:
53 if ((s32)Memory::Read32(address) <= value) { 53 if ((s32)Memory::Read32(address) < value) {
54 Kernel::WaitCurrentThread_ArbitrateAddress(address); 54 Kernel::WaitCurrentThread_ArbitrateAddress(address);
55 GetCurrentThread()->WakeAfterDelay(nanoseconds); 55 GetCurrentThread()->WakeAfterDelay(nanoseconds);
56 } 56 }
57 break; 57 break;
58 case ArbitrationType::DecrementAndWaitIfLessThan: 58 case ArbitrationType::DecrementAndWaitIfLessThan:
59 { 59 {
60 s32 memory_value = Memory::Read32(address) - 1; 60 s32 memory_value = Memory::Read32(address);
61 Memory::Write32(address, memory_value); 61 if (memory_value < value) {
62 if (memory_value <= value) { 62 // Only change the memory value if the thread should wait
63 Memory::Write32(address, (s32)memory_value - 1);
63 Kernel::WaitCurrentThread_ArbitrateAddress(address); 64 Kernel::WaitCurrentThread_ArbitrateAddress(address);
64 } 65 }
65 break; 66 break;
66 } 67 }
67 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: 68 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout:
68 { 69 {
69 s32 memory_value = Memory::Read32(address) - 1; 70 s32 memory_value = Memory::Read32(address);
70 Memory::Write32(address, memory_value); 71 if (memory_value < value) {
71 if (memory_value <= value) { 72 // Only change the memory value if the thread should wait
73 Memory::Write32(address, (s32)memory_value - 1);
72 Kernel::WaitCurrentThread_ArbitrateAddress(address); 74 Kernel::WaitCurrentThread_ArbitrateAddress(address);
73 GetCurrentThread()->WakeAfterDelay(nanoseconds); 75 GetCurrentThread()->WakeAfterDelay(nanoseconds);
74 } 76 }
@@ -82,6 +84,13 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
82 84
83 HLE::Reschedule(__func__); 85 HLE::Reschedule(__func__);
84 86
87 // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep
88 if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
89 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
90
91 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
92 ErrorSummary::StatusChanged, ErrorLevel::Info);
93 }
85 return RESULT_SUCCESS; 94 return RESULT_SUCCESS;
86} 95}
87 96
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index c08fc1c7a..bf32f653d 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -300,7 +300,7 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
300 300
301 thread->waitsynch_waited = false; 301 thread->waitsynch_waited = false;
302 302
303 if (thread->status == THREADSTATUS_WAIT_SYNCH) { 303 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
304 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 304 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
305 ErrorSummary::StatusChanged, ErrorLevel::Info)); 305 ErrorSummary::StatusChanged, ErrorLevel::Info));
306 306