kernel: Implement thread pinning support (#2840)

* kernel: Implement Thread pinning support

This commit adds support for 8.x thread pinning changes and implement SynchronizePreemptionState syscall.

Based on kernel 13.x reverse.

* Address gdkchan's comment

* kernel: fix missing critical section leave in SetActivity

Fix Unity games

* Implement missing bits on the interrupt handler and inline update pinning function as it cannot be generic

* Fix some bugs in SetActivity and SetCoreAndAffinityMask

* Address gdkchan's comments
This commit is contained in:
Mary 2021-12-30 10:55:06 +01:00 committed by GitHub
parent 8544b1445b
commit e96ef6d532
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 436 additions and 95 deletions

View file

@ -46,6 +46,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KAddressArbiter AddressArbiter { get; private set; }
public long[] RandomEntropy { get; private set; }
public KThread[] PinnedThreads { get; private set; }
private bool _signaled;
@ -102,6 +103,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
Capabilities = new KProcessCapabilities();
RandomEntropy = new long[KScheduler.CpuCoresCount];
PinnedThreads = new KThread[KScheduler.CpuCoresCount];
// TODO: Remove once we no longer need to initialize it externally.
HandleTable = new KHandleTable(context);
@ -749,7 +751,24 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
KThread currentThread = KernelStatic.GetCurrentThread();
if (currentThread.IsSchedulable)
if (currentThread.Owner != null &&
currentThread.GetUserDisableCount() != 0 &&
currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null)
{
KernelContext.CriticalSection.Enter();
currentThread.Owner.PinThread(currentThread);
currentThread.SetUserInterruptFlag();
if (currentThread.IsSchedulable)
{
KernelContext.Schedulers[currentThread.CurrentCore].Schedule();
}
KernelContext.CriticalSection.Leave();
}
else if (currentThread.IsSchedulable)
{
KernelContext.Schedulers[currentThread.CurrentCore].Schedule();
}
@ -952,6 +971,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
KernelContext.CriticalSection.Enter();
if (currentThread != null && PinnedThreads[currentThread.CurrentCore] == currentThread)
{
UnpinThread(currentThread);
}
foreach (KThread thread in _threads)
{
if ((thread.SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.TerminationPending)
@ -1139,5 +1163,35 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return KernelResult.InvalidState;
}
public void PinThread(KThread thread)
{
if (!thread.TerminationRequested)
{
PinnedThreads[thread.CurrentCore] = thread;
thread.Pin();
KernelContext.ThreadReselectionRequested = true;
}
}
public void UnpinThread(KThread thread)
{
if (!thread.TerminationRequested)
{
thread.Unpin();
PinnedThreads[thread.CurrentCore] = null;
KernelContext.ThreadReselectionRequested = true;
}
}
public bool IsExceptionUserThread(KThread thread)
{
// TODO
return false;
}
}
}