From e96ef6d53250b72d084f7e6baf13e9bab485bca2 Mon Sep 17 00:00:00 2001
From: Mary <me@thog.eu>
Date: Thu, 30 Dec 2021 10:55:06 +0100
Subject: 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
---
 Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

(limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs')

diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
index 0982ceff..0c51b7b9 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
@@ -36,6 +36,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
         private readonly KThread _idleThread;
 
         public KThread PreviousThread => _previousThread;
+        public KThread CurrentThread => _currentThread;
         public long LastContextSwitchTime { get; private set; }
         public long TotalIdleTimeTicks => _idleThread.TotalTimeRunning;
 
@@ -87,6 +88,26 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             {
                 KThread thread = context.PriorityQueue.ScheduledThreads(core).FirstOrDefault();
 
+                if (thread != null &&
+                    thread.Owner != null &&
+                    thread.Owner.PinnedThreads[core] != null &&
+                    thread.Owner.PinnedThreads[core] != thread)
+                {
+                    KThread candidate = thread.Owner.PinnedThreads[core];
+
+                    if (candidate.KernelWaitersCount == 0 && !thread.Owner.IsExceptionUserThread(candidate))
+                    {
+                        if (candidate.SchedFlags == ThreadSchedState.Running)
+                        {
+                            thread = candidate;
+                        }
+                        else
+                        {
+                            thread = null;
+                        }
+                    }
+                }
+
                 scheduledCoresMask |= context.Schedulers[core].SelectThread(thread);
             }
 
-- 
cgit v1.2.3-70-g09d2