SVC: Fixed ArbitrateAddress to behave as it does on hardware.
This was verified with hwtests that i plan to upload later on.
This commit is contained in:
parent
031443199b
commit
29032ce9b6
|
@ -45,30 +45,32 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
|
|||
|
||||
// Wait current thread (acquire the arbiter)...
|
||||
case ArbitrationType::WaitIfLessThan:
|
||||
if ((s32)Memory::Read32(address) <= value) {
|
||||
if ((s32)Memory::Read32(address) < value) {
|
||||
Kernel::WaitCurrentThread_ArbitrateAddress(address);
|
||||
}
|
||||
break;
|
||||
case ArbitrationType::WaitIfLessThanWithTimeout:
|
||||
if ((s32)Memory::Read32(address) <= value) {
|
||||
if ((s32)Memory::Read32(address) < value) {
|
||||
Kernel::WaitCurrentThread_ArbitrateAddress(address);
|
||||
GetCurrentThread()->WakeAfterDelay(nanoseconds);
|
||||
}
|
||||
break;
|
||||
case ArbitrationType::DecrementAndWaitIfLessThan:
|
||||
{
|
||||
s32 memory_value = Memory::Read32(address) - 1;
|
||||
Memory::Write32(address, memory_value);
|
||||
if (memory_value <= value) {
|
||||
s32 memory_value = Memory::Read32(address);
|
||||
if (memory_value < value) {
|
||||
// Only change the memory value if the thread should wait
|
||||
Memory::Write32(address, (s32)memory_value - 1);
|
||||
Kernel::WaitCurrentThread_ArbitrateAddress(address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout:
|
||||
{
|
||||
s32 memory_value = Memory::Read32(address) - 1;
|
||||
Memory::Write32(address, memory_value);
|
||||
if (memory_value <= value) {
|
||||
s32 memory_value = Memory::Read32(address);
|
||||
if (memory_value < value) {
|
||||
// Only change the memory value if the thread should wait
|
||||
Memory::Write32(address, (s32)memory_value - 1);
|
||||
Kernel::WaitCurrentThread_ArbitrateAddress(address);
|
||||
GetCurrentThread()->WakeAfterDelay(nanoseconds);
|
||||
}
|
||||
|
@ -82,6 +84,13 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
|
|||
|
||||
HLE::Reschedule(__func__);
|
||||
|
||||
// The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep
|
||||
if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
|
||||
type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
|
||||
|
||||
return ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
|
||||
ErrorSummary::StatusChanged, ErrorLevel::Info);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -300,7 +300,7 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
|
|||
|
||||
thread->waitsynch_waited = false;
|
||||
|
||||
if (thread->status == THREADSTATUS_WAIT_SYNCH) {
|
||||
if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
|
||||
thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
|
||||
ErrorSummary::StatusChanged, ErrorLevel::Info));
|
||||
|
||||
|
|
Reference in New Issue