diff options
author | gdkchan <gab.dark.100@gmail.com> | 2020-12-01 20:23:43 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-02 00:23:43 +0100 |
commit | cf6cd714884c41e9550757e364c2f4f5b04fc7f3 (patch) | |
tree | bea748b4d1a350e5b8075d63ec9d39d49693829d /Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | |
parent | 461c24092ae6e148d896c18aa3e86220c89981f8 (diff) |
IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel (#1458)
* IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel
* Fix for applet transfer memory + some nits
* Keep handles if possible to avoid server handle table exhaustion
* Fix IPC ZeroFill bug
* am: Correctly implement CreateManagedDisplayLayer and implement CreateManagedDisplaySeparableLayer
CreateManagedDisplaySeparableLayer is requires since 10.x+ when appletResourceUserId != 0
* Make it exit properly
* Make ServiceNotImplementedException show the full message again
* Allow yielding execution to avoid starving other threads
* Only wait if active
* Merge IVirtualMemoryManager and IAddressSpaceManager
* Fix Ro loading data from the wrong process
Co-authored-by: Thog <me@thog.eu>
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 90 |
1 files changed, 50 insertions, 40 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 27ff3883..f523cb9c 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -31,6 +31,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public ulong CondVarAddress { get; set; } private ulong _entrypoint; + private ThreadStart _customThreadStart; public ulong MutexAddress { get; set; } @@ -48,12 +49,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public LinkedListNode<KThread>[] SiblingsPerCore { get; private set; } - public LinkedList<KThread> Withholder { get; set; } + public LinkedList<KThread> Withholder { get; set; } public LinkedListNode<KThread> WithholderNode { get; set; } public LinkedListNode<KThread> ProcessListNode { get; set; } - private LinkedList<KThread> _mutexWaiters; + private LinkedList<KThread> _mutexWaiters; private LinkedListNode<KThread> _mutexWaiterNode; public KThread MutexOwner { get; private set; } @@ -65,24 +66,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KernelResult ObjSyncResult { get; set; } public int DynamicPriority { get; set; } - public int CurrentCore { get; set; } - public int BasePriority { get; set; } - public int PreferredCore { get; set; } + public int CurrentCore { get; set; } + public int BasePriority { get; set; } + public int PreferredCore { get; set; } private long _affinityMaskOverride; - private int _preferredCoreOverride; + private int _preferredCoreOverride; #pragma warning disable CS0649 - private int _affinityOverrideCount; + private int _affinityOverrideCount; #pragma warning restore CS0649 public ThreadSchedState SchedFlags { get; private set; } private int _shallBeTerminated; - public bool ShallBeTerminated { get => _shallBeTerminated != 0; set => _shallBeTerminated = value ? 1 : 0; } + public bool ShallBeTerminated + { + get => _shallBeTerminated != 0; + set => _shallBeTerminated = value ? 1 : 0; + } public bool SyncCancelled { get; set; } - public bool WaitingSync { get; set; } + public bool WaitingSync { get; set; } private bool _hasExited; private bool _hasBeenInitialized; @@ -98,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KThread(KernelContext context) : base(context) { - _scheduler = KernelContext.Scheduler; + _scheduler = KernelContext.Scheduler; _schedulingData = KernelContext.Scheduler.SchedulingData; WaitSyncObjects = new KSynchronizationObject[MaxWaitSyncObjects]; @@ -110,14 +115,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } public KernelResult Initialize( - ulong entrypoint, - ulong argsPtr, - ulong stackTop, - int priority, - int defaultCpuCore, - KProcess owner, - ThreadType type = ThreadType.User, - ThreadStart customHostThreadStart = null) + ulong entrypoint, + ulong argsPtr, + ulong stackTop, + int priority, + int defaultCpuCore, + KProcess owner, + ThreadType type, + ThreadStart customThreadStart = null) { if ((uint)type > 3) { @@ -135,11 +140,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading CurrentCore = PreferredCore; DynamicPriority = priority; - BasePriority = priority; + BasePriority = priority; ObjSyncResult = KernelResult.ThreadNotStarted; _entrypoint = entrypoint; + _customThreadStart = customThreadStart; if (type == ThreadType.User) { @@ -162,18 +168,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading owner.IncrementReferenceCount(); owner.IncrementThreadCount(); - is64Bits = (owner.MmuFlags & 1) != 0; + is64Bits = owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit); } else { is64Bits = true; } - HostThread = new Thread(customHostThreadStart ?? (() => ThreadStart(entrypoint))); + HostThread = new Thread(ThreadStart); Context = CpuContext.CreateExecutionContext(); - bool isAarch32 = (Owner.MmuFlags & 1) == 0; + bool isAarch32 = !Owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit); Context.IsAarch32 = isAarch32; @@ -189,7 +195,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } Context.CntfrqEl0 = 19200000; - Context.Tpidr = (long)_tlsAddress; + Context.Tpidr = (long)_tlsAddress; owner.SubscribeThreadEventHandlers(Context); @@ -249,7 +255,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { KThread currentThread = KernelContext.Scheduler.GetCurrentThread(); - while (SchedFlags != ThreadSchedState.TerminationPending && + while (SchedFlags != ThreadSchedState.TerminationPending && currentThread.SchedFlags != ThreadSchedState.TerminationPending && !currentThread.ShallBeTerminated) { @@ -351,7 +357,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading Context.RequestInterrupt(); } - SignaledObj = null; + SignaledObj = null; ObjSyncResult = KernelResult.ThreadTerminating; ReleaseAndResume(); @@ -524,7 +530,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // If the candidate was scheduled after the current thread, then it's not worth it, // unless the priority is higher than the current one. if (nextThreadOnCurrentQueue.LastScheduledTime >= thread.LastScheduledTime || - nextThreadOnCurrentQueue.DynamicPriority < thread.DynamicPriority) + nextThreadOnCurrentQueue.DynamicPriority < thread.DynamicPriority) { yield return thread; } @@ -701,7 +707,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } else { - SignaledObj = null; + SignaledObj = null; ObjSyncResult = KernelResult.Cancelled; SetNewSchedFlags(ThreadSchedState.Running); @@ -734,14 +740,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (useOverride) { _preferredCoreOverride = newCore; - _affinityMaskOverride = newAffinityMask; + _affinityMaskOverride = newAffinityMask; } else { long oldAffinityMask = AffinityMask; PreferredCore = newCore; - AffinityMask = newAffinityMask; + AffinityMask = newAffinityMask; if (oldAffinityMask != newAffinityMask) { @@ -783,7 +789,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private void CombineForcePauseFlags() { - ThreadSchedState oldFlags = SchedFlags; + ThreadSchedState oldFlags = SchedFlags; ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask; SchedFlags = lowNibble | _forcePauseFlags; @@ -1143,19 +1149,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - private void ThreadStart(ulong entrypoint) + private void ThreadStart() { - Owner.CpuContext.Execute(Context, entrypoint); + KernelStatic.SetKernelContext(KernelContext); - ThreadExit(); - - Context.Dispose(); - } + if (_customThreadStart != null) + { + _customThreadStart(); + } + else + { + Owner.Context.Execute(Context, _entrypoint); + } - private void ThreadExit() - { KernelContext.Scheduler.ExitThread(this); KernelContext.Scheduler.RemoveThread(this); + + Context.Dispose(); } public bool IsCurrentHostThread() @@ -1203,9 +1213,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // Wake up all threads that may be waiting for a mutex being held by this thread. foreach (KThread thread in _mutexWaiters) { - thread.MutexOwner = null; + thread.MutexOwner = null; thread._preferredCoreOverride = 0; - thread.ObjSyncResult = KernelResult.InvalidState; + thread.ObjSyncResult = KernelResult.InvalidState; thread.ReleaseAndResume(); } |