diff options
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading')
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs | 37 | ||||
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs | 11 | ||||
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs | 9 | ||||
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 45 | ||||
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KThreadContext.cs | 18 | ||||
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs | 3 |
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(); } |