aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-02-18 20:52:06 -0300
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-02-19 10:52:06 +1100
commit932224f05112180aa5f52162cbbc3a17c339075f (patch)
treeeed53f37bfd78db97d6f8301c021b7de9dd3becf /Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
parentdd00a4b62d48b7d55a6e66a69a83f09267d34143 (diff)
ARM exclusive monitor and multicore fixes (#589)
* Implement ARM exclusive load/store with compare exchange insts, and enable multicore by default * Fix comment typo * Support Linux and OSX on MemoryAlloc and CompareExchange128, some cleanup * Use intel syntax on assembly code * Adjust identation * Add CPUID check and fix exclusive reservation granule size * Update schema multicore scheduling default value * Make the cpu id check code lower case aswell
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs')
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs141
1 files changed, 41 insertions, 100 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
index faeea5c5..b11df61e 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
@@ -228,43 +228,31 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
+ int mutexValue, newMutexValue;
- if (!KernelTransfer.UserToKernelInt32(_system, address, out int mutexValue))
+ do
{
- //Invalid address.
- currentProcess.CpuMemory.ClearExclusive(0);
-
- requester.SignaledObj = null;
- requester.ObjSyncResult = KernelResult.InvalidMemState;
-
- return null;
- }
-
- while (true)
- {
- if (currentProcess.CpuMemory.TestExclusive(0, (long)address))
+ if (!KernelTransfer.UserToKernelInt32(_system, address, out mutexValue))
{
- if (mutexValue != 0)
- {
- //Update value to indicate there is a mutex waiter now.
- currentProcess.CpuMemory.WriteInt32((long)address, mutexValue | HasListenersMask);
- }
- else
- {
- //No thread owning the mutex, assign to requesting thread.
- currentProcess.CpuMemory.WriteInt32((long)address, requester.ThreadHandleForUserMutex);
- }
-
- currentProcess.CpuMemory.ClearExclusiveForStore(0);
+ //Invalid address.
+ requester.SignaledObj = null;
+ requester.ObjSyncResult = KernelResult.InvalidMemState;
- break;
+ return null;
}
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
-
- mutexValue = currentProcess.CpuMemory.ReadInt32((long)address);
+ if (mutexValue != 0)
+ {
+ //Update value to indicate there is a mutex waiter now.
+ newMutexValue = mutexValue | HasListenersMask;
+ }
+ else
+ {
+ //No thread owning the mutex, assign to requesting thread.
+ newMutexValue = requester.ThreadHandleForUserMutex;
+ }
}
+ while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, mutexValue, newMutexValue));
if (mutexValue == 0)
{
@@ -392,9 +380,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
- //If ShouldDecrement is true, do atomic decrement of the value at Address.
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
-
if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
{
_system.CriticalSection.Leave();
@@ -404,25 +389,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
if (shouldDecrement)
{
- while (currentValue < value)
- {
- if (currentProcess.CpuMemory.TestExclusive(0, (long)address))
- {
- currentProcess.CpuMemory.WriteInt32((long)address, currentValue - 1);
-
- currentProcess.CpuMemory.ClearExclusiveForStore(0);
-
- break;
- }
-
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
-
- currentValue = currentProcess.CpuMemory.ReadInt32((long)address);
- }
+ currentValue = currentProcess.CpuMemory.AtomicDecrementInt32((long)address) + 1;
}
- currentProcess.CpuMemory.ClearExclusive(0);
-
if (currentValue < value)
{
if (timeout == 0)
@@ -511,39 +480,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
+ int currentValue;
- if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
+ do
{
- _system.CriticalSection.Leave();
-
- return KernelResult.InvalidMemState;
- }
-
- while (currentValue == value)
- {
- if (currentProcess.CpuMemory.TestExclusive(0, (long)address))
+ if (!KernelTransfer.UserToKernelInt32(_system, address, out currentValue))
{
- currentProcess.CpuMemory.WriteInt32((long)address, currentValue + 1);
-
- currentProcess.CpuMemory.ClearExclusiveForStore(0);
+ _system.CriticalSection.Leave();
- break;
+ return KernelResult.InvalidMemState;
}
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
-
- currentValue = currentProcess.CpuMemory.ReadInt32((long)address);
- }
-
- currentProcess.CpuMemory.ClearExclusive(0);
-
- if (currentValue != value)
- {
- _system.CriticalSection.Leave();
+ if (currentValue != value)
+ {
+ _system.CriticalSection.Leave();
- return KernelResult.InvalidState;
+ return KernelResult.InvalidState;
+ }
}
+ while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, currentValue, currentValue + 1));
WakeArbiterThreads(address, count);
@@ -582,39 +537,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
+ int currentValue;
- if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
+ do
{
- _system.CriticalSection.Leave();
-
- return KernelResult.InvalidMemState;
- }
-
- while (currentValue == value)
- {
- if (currentProcess.CpuMemory.TestExclusive(0, (long)address))
+ if (!KernelTransfer.UserToKernelInt32(_system, address, out currentValue))
{
- currentProcess.CpuMemory.WriteInt32((long)address, currentValue + offset);
-
- currentProcess.CpuMemory.ClearExclusiveForStore(0);
+ _system.CriticalSection.Leave();
- break;
+ return KernelResult.InvalidMemState;
}
- currentProcess.CpuMemory.SetExclusive(0, (long)address);
-
- currentValue = currentProcess.CpuMemory.ReadInt32((long)address);
- }
-
- currentProcess.CpuMemory.ClearExclusive(0);
-
- if (currentValue != value)
- {
- _system.CriticalSection.Leave();
+ if (currentValue != value)
+ {
+ _system.CriticalSection.Leave();
- return KernelResult.InvalidState;
+ return KernelResult.InvalidState;
+ }
}
+ while (!currentProcess.CpuMemory.AtomicCompareExchangeInt32((long)address, currentValue, currentValue + offset));
WakeArbiterThreads(address, count);