aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/Threading
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading')
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs37
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs11
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs9
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs45
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KThreadContext.cs18
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs3
6 files changed, 73 insertions, 50 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
index f53b43b3..a5f9df5e 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs
@@ -1,5 +1,6 @@
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.Horizon.Common;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -24,14 +25,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_arbiterThreads = new List<KThread>();
}
- public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
+ public Result ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
{
KThread currentThread = KernelStatic.GetCurrentThread();
_context.CriticalSection.Enter();
currentThread.SignaledObj = null;
- currentThread.ObjSyncResult = KernelResult.Success;
+ currentThread.ObjSyncResult = Result.Success;
KProcess currentProcess = KernelStatic.GetCurrentProcess();
@@ -46,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
_context.CriticalSection.Leave();
- return 0;
+ return Result.Success;
}
KThread mutexOwner = currentProcess.HandleTable.GetObject<KThread>(ownerHandle);
@@ -78,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
return currentThread.ObjSyncResult;
}
- public KernelResult ArbitrateUnlock(ulong mutexAddress)
+ public Result ArbitrateUnlock(ulong mutexAddress)
{
_context.CriticalSection.Enter();
@@ -86,14 +87,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
(int mutexValue, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress);
- KernelResult result = KernelResult.Success;
+ Result result = Result.Success;
if (!KernelTransfer.KernelToUser(mutexAddress, mutexValue))
{
result = KernelResult.InvalidMemState;
}
- if (result != KernelResult.Success && newOwnerThread != null)
+ if (result != Result.Success && newOwnerThread != null)
{
newOwnerThread.SignaledObj = null;
newOwnerThread.ObjSyncResult = result;
@@ -104,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
return result;
}
- public KernelResult WaitProcessWideKeyAtomic(ulong mutexAddress, ulong condVarAddress, int threadHandle, long timeout)
+ public Result WaitProcessWideKeyAtomic(ulong mutexAddress, ulong condVarAddress, int threadHandle, long timeout)
{
_context.CriticalSection.Enter();
@@ -185,7 +186,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
newOwnerThread.SignaledObj = null;
- newOwnerThread.ObjSyncResult = KernelResult.Success;
+ newOwnerThread.ObjSyncResult = Result.Success;
newOwnerThread.ReleaseAndResume();
}
@@ -247,7 +248,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
// We now own the mutex.
requester.SignaledObj = null;
- requester.ObjSyncResult = KernelResult.Success;
+ requester.ObjSyncResult = Result.Success;
requester.ReleaseAndResume();
@@ -273,7 +274,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
}
- public KernelResult WaitForAddressIfEqual(ulong address, int value, long timeout)
+ public Result WaitForAddressIfEqual(ulong address, int value, long timeout)
{
KThread currentThread = KernelStatic.GetCurrentThread();
@@ -344,7 +345,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
return KernelResult.InvalidState;
}
- public KernelResult WaitForAddressIfLessThan(ulong address, int value, bool shouldDecrement, long timeout)
+ public Result WaitForAddressIfLessThan(ulong address, int value, bool shouldDecrement, long timeout)
{
KThread currentThread = KernelStatic.GetCurrentThread();
@@ -422,7 +423,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
return KernelResult.InvalidState;
}
- public KernelResult Signal(ulong address, int count)
+ public Result Signal(ulong address, int count)
{
_context.CriticalSection.Enter();
@@ -430,10 +431,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_context.CriticalSection.Leave();
- return KernelResult.Success;
+ return Result.Success;
}
- public KernelResult SignalAndIncrementIfEqual(ulong address, int value, int count)
+ public Result SignalAndIncrementIfEqual(ulong address, int value, int count)
{
_context.CriticalSection.Enter();
@@ -467,10 +468,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_context.CriticalSection.Leave();
- return KernelResult.Success;
+ return Result.Success;
}
- public KernelResult SignalAndModifyIfEqual(ulong address, int value, int count)
+ public Result SignalAndModifyIfEqual(ulong address, int value, int count)
{
_context.CriticalSection.Enter();
@@ -539,7 +540,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_context.CriticalSection.Leave();
- return KernelResult.Success;
+ return Result.Success;
}
private void WakeArbiterThreads(ulong address, int count)
@@ -547,7 +548,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
static void RemoveArbiterThread(KThread thread)
{
thread.SignaledObj = null;
- thread.ObjSyncResult = KernelResult.Success;
+ thread.ObjSyncResult = Result.Success;
thread.ReleaseAndResume();
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs
index d378b81e..d9e7befa 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs
@@ -1,4 +1,5 @@
using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.Horizon.Common;
namespace Ryujinx.HLE.HOS.Kernel.Threading
{
@@ -27,16 +28,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.CriticalSection.Leave();
}
- public KernelResult Clear()
+ public Result Clear()
{
_signaled = false;
- return KernelResult.Success;
+ return Result.Success;
}
- public KernelResult ClearIfSignaled()
+ public Result ClearIfSignaled()
{
- KernelResult result;
+ Result result;
KernelContext.CriticalSection.Enter();
@@ -44,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
_signaled = false;
- result = KernelResult.Success;
+ result = Result.Success;
}
else
{
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs
index 419f1536..01b65f55 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs
@@ -1,4 +1,5 @@
using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.Horizon.Common;
using System;
using System.Collections.Generic;
@@ -13,11 +14,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_context = context;
}
- public KernelResult WaitFor(Span<KSynchronizationObject> syncObjs, long timeout, out int handleIndex)
+ public Result WaitFor(Span<KSynchronizationObject> syncObjs, long timeout, out int handleIndex)
{
handleIndex = 0;
- KernelResult result = KernelResult.TimedOut;
+ Result result = KernelResult.TimedOut;
_context.CriticalSection.Enter();
@@ -33,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_context.CriticalSection.Leave();
- return KernelResult.Success;
+ return Result.Success;
}
if (timeout == 0)
@@ -122,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
{
thread.SignaledObj = syncObj;
- thread.ObjSyncResult = KernelResult.Success;
+ thread.ObjSyncResult = Result.Success;
thread.Reschedule(ThreadSchedState.Running);
}
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
index b9dd91ef..6fd49605 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
@@ -3,6 +3,7 @@ using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
+using Ryujinx.Horizon.Common;
using System;
using System.Collections.Generic;
using System.Numerics;
@@ -79,7 +80,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private ThreadSchedState _forcePauseFlags;
private ThreadSchedState _forcePausePermissionFlags;
- public KernelResult ObjSyncResult { get; set; }
+ public Result ObjSyncResult { get; set; }
public int BasePriority { get; set; }
public int PreferredCore { get; set; }
@@ -130,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_activityOperationLock = new object();
}
- public KernelResult Initialize(
+ public Result Initialize(
ulong entrypoint,
ulong argsPtr,
ulong stackTop,
@@ -145,8 +146,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
throw new ArgumentException($"Invalid thread type \"{type}\".");
}
- ThreadContext = new KThreadContext();
-
PreferredCore = cpuCore;
AffinityMask |= 1UL << cpuCore;
@@ -166,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
if (type == ThreadType.User)
{
- if (owner.AllocateThreadLocalStorage(out _tlsAddress) != KernelResult.Success)
+ if (owner.AllocateThreadLocalStorage(out _tlsAddress) != Result.Success)
{
return KernelResult.OutOfMemory;
}
@@ -194,6 +193,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
+ ThreadContext = new KThreadContext(Context);
+
Context.IsAarch32 = !is64Bits;
Context.SetX(0, argsPtr);
@@ -230,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
KernelContext.CriticalSection.Leave();
- return KernelResult.Success;
+ return Result.Success;
}
_forcePauseFlags |= ThreadSchedState.ProcessPauseFlag;
@@ -241,10 +242,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
}
- return KernelResult.Success;
+ return Result.Success;
}
- public KernelResult Start()
+ public Result Start()
{
if (!KernelContext.KernelInitialized)
{
@@ -260,7 +261,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.CriticalSection.Leave();
}
- KernelResult result = KernelResult.ThreadTerminating;
+ Result result = KernelResult.ThreadTerminating;
KernelContext.CriticalSection.Enter();
@@ -287,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
StartHostThread();
- result = KernelResult.Success;
+ result = Result.Success;
break;
}
else
@@ -465,7 +466,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
return -1;
}
- public KernelResult Sleep(long timeout)
+ public Result Sleep(long timeout)
{
KernelContext.CriticalSection.Enter();
@@ -490,7 +491,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.TimeManager.UnscheduleFutureInvocation(this);
}
- return 0;
+ return Result.Success;
}
public void SetPriority(int priority)
@@ -534,11 +535,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
}
- public KernelResult SetActivity(bool pause)
+ public Result SetActivity(bool pause)
{
lock (_activityOperationLock)
{
- KernelResult result = KernelResult.Success;
+ Result result = Result.Success;
KernelContext.CriticalSection.Enter();
@@ -581,7 +582,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.CriticalSection.Leave();
- if (result == KernelResult.Success && pause)
+ if (result == Result.Success && pause)
{
bool isThreadRunning = true;
@@ -628,7 +629,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
}
- public KernelResult GetThreadContext3(out ThreadContext context)
+ public Result GetThreadContext3(out ThreadContext context)
{
context = default;
@@ -651,7 +652,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.CriticalSection.Leave();
}
- return KernelResult.Success;
+ return Result.Success;
}
private static uint GetPsr(IExecutionContext context)
@@ -739,7 +740,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.CriticalSection.Leave();
}
- public KernelResult SetCoreAndAffinityMask(int newCore, ulong newAffinityMask)
+ public Result SetCoreAndAffinityMask(int newCore, ulong newAffinityMask)
{
lock (_activityOperationLock)
{
@@ -838,7 +839,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KernelContext.CriticalSection.Leave();
}
- return KernelResult.Success;
+ return Result.Success;
}
}
@@ -1259,6 +1260,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
if (_customThreadStart != null)
{
_customThreadStart();
+
+ // Ensure that anything trying to join the HLE thread is unblocked.
+ Exit();
+ HandlePostSyscall();
}
else
{
@@ -1304,7 +1309,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
Owner?.RemoveThread(this);
- if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != KernelResult.Success)
+ if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != Result.Success)
{
throw new InvalidOperationException("Unexpected failure freeing thread local storage.");
}
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThreadContext.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThreadContext.cs
index a7e9c4b3..e8ad53c2 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KThreadContext.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThreadContext.cs
@@ -1,11 +1,25 @@
-using System.Threading;
+using Ryujinx.Cpu;
+using Ryujinx.Horizon.Common;
+using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Threading
{
- class KThreadContext
+ class KThreadContext : IThreadContext
{
+ private readonly IExecutionContext _context;
+
+ public bool Running => _context.Running;
+ public ulong TlsAddress => (ulong)_context.TpidrroEl0;
+
+ public ulong GetX(int index) => _context.GetX(index);
+
private int _locked;
+ public KThreadContext(IExecutionContext context)
+ {
+ _context = context;
+ }
+
public bool Lock()
{
return Interlocked.Exchange(ref _locked, 1) == 0;
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs
index 7aee0b57..b46122be 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs
@@ -1,4 +1,5 @@
using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.Horizon.Common;
namespace Ryujinx.HLE.HOS.Kernel.Threading
{
@@ -16,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_parent.ReadableEvent.Signal();
}
- public KernelResult Clear()
+ public Result Clear()
{
return _parent.ReadableEvent.Clear();
}