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:
parent
8544b1445b
commit
e96ef6d532
9 changed files with 436 additions and 95 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue