diff options
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs index 166cf064..71ad712e 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs @@ -2,6 +2,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; using System.Collections.Generic; using System.Linq; +using System.Threading; namespace Ryujinx.HLE.HOS.Kernel.Threading { @@ -228,18 +229,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + if (!currentProcess.CpuMemory.IsMapped(address)) + { + // Invalid address. + requester.SignaledObj = null; + requester.ObjSyncResult = KernelResult.InvalidMemState; + + return null; + } + + ref int mutexRef = ref currentProcess.CpuMemory.GetRef<int>(address); + int mutexValue, newMutexValue; do { - if (!KernelTransfer.UserToKernelInt32(_system, address, out mutexValue)) - { - // Invalid address. - requester.SignaledObj = null; - requester.ObjSyncResult = KernelResult.InvalidMemState; - - return null; - } + mutexValue = mutexRef; if (mutexValue != 0) { @@ -252,7 +257,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading newMutexValue = requester.ThreadHandleForUserMutex; } } - while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, mutexValue, newMutexValue)); + while (Interlocked.CompareExchange(ref mutexRef, newMutexValue, mutexValue) != mutexValue); if (mutexValue == 0) { @@ -389,7 +394,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (shouldDecrement) { - currentValue = currentProcess.CpuMemory.AtomicDecrementInt32((long)address) + 1; + currentValue = Interlocked.Decrement(ref currentProcess.CpuMemory.GetRef<int>(address)) + 1; } if (currentValue < value) @@ -480,16 +485,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + if (!currentProcess.CpuMemory.IsMapped(address)) + { + _system.CriticalSection.Leave(); + + return KernelResult.InvalidMemState; + } + + ref int valueRef = ref currentProcess.CpuMemory.GetRef<int>(address); + int currentValue; do { - if (!KernelTransfer.UserToKernelInt32(_system, address, out currentValue)) - { - _system.CriticalSection.Leave(); - - return KernelResult.InvalidMemState; - } + currentValue = valueRef; if (currentValue != value) { @@ -498,7 +507,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return KernelResult.InvalidState; } } - while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, currentValue, currentValue + 1)); + while (Interlocked.CompareExchange(ref valueRef, currentValue + 1, currentValue) != currentValue); WakeArbiterThreads(address, count); @@ -537,16 +546,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + if (!currentProcess.CpuMemory.IsMapped(address)) + { + _system.CriticalSection.Leave(); + + return KernelResult.InvalidMemState; + } + + ref int valueRef = ref currentProcess.CpuMemory.GetRef<int>(address); + int currentValue; do { - if (!KernelTransfer.UserToKernelInt32(_system, address, out currentValue)) - { - _system.CriticalSection.Leave(); - - return KernelResult.InvalidMemState; - } + currentValue = valueRef; if (currentValue != value) { @@ -555,7 +568,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return KernelResult.InvalidState; } } - while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, currentValue, currentValue + offset)); + while (Interlocked.CompareExchange(ref valueRef, currentValue + offset, currentValue) != currentValue); WakeArbiterThreads(address, count); |
