aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-12-01 20:23:43 -0300
committerGitHub <noreply@github.com>2020-12-02 00:23:43 +0100
commitcf6cd714884c41e9550757e364c2f4f5b04fc7f3 (patch)
treebea748b4d1a350e5b8075d63ec9d39d49693829d /Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
parent461c24092ae6e148d896c18aa3e86220c89981f8 (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.cs90
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();
}