diff options
author | Mary <me@thog.eu> | 2021-12-30 10:55:06 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-30 10:55:06 +0100 |
commit | e96ef6d53250b72d084f7e6baf13e9bab485bca2 (patch) | |
tree | 5701772c89dbad3bf51bdf736714f9feb889472a /Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | |
parent | 8544b1445b33381fca63714249ac36598c413004 (diff) |
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
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 0a74eace..649cfb93 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -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; + } } }
\ No newline at end of file |