diff options
author | gdkchan <gab.dark.100@gmail.com> | 2018-12-18 03:33:36 -0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-18 03:33:36 -0200 |
commit | 0039bb639493b2d1e2764cae380311ba8e87704b (patch) | |
tree | 63a912a95c8261775c2acb8a5b9ca0f10ad4ae33 /Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs | |
parent | 2534a7f10c627810e6e0272b4cc9758e90f733c1 (diff) |
Refactor SVC handler (#540)
* Refactor SVC handler
* Get rid of KernelErr
* Split kernel code files into multiple folders
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs new file mode 100644 index 00000000..835c2a2f --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs @@ -0,0 +1,149 @@ +using System; +using System.Threading; + +namespace Ryujinx.HLE.HOS.Kernel.Threading +{ + partial class KScheduler + { + private const int RoundRobinTimeQuantumMs = 10; + + private int _currentCore; + + public bool MultiCoreScheduling { get; set; } + + public HleCoreManager CoreManager { get; private set; } + + private bool _keepPreempting; + + public void StartAutoPreemptionThread() + { + Thread preemptionThread = new Thread(PreemptCurrentThread); + + _keepPreempting = true; + + preemptionThread.Start(); + } + + public void ContextSwitch() + { + lock (CoreContexts) + { + if (MultiCoreScheduling) + { + int selectedCount = 0; + + for (int core = 0; core < CpuCoresCount; core++) + { + KCoreContext coreContext = CoreContexts[core]; + + if (coreContext.ContextSwitchNeeded && (coreContext.CurrentThread?.Context.IsCurrentThread() ?? false)) + { + coreContext.ContextSwitch(); + } + + if (coreContext.CurrentThread?.Context.IsCurrentThread() ?? false) + { + selectedCount++; + } + } + + if (selectedCount == 0) + { + CoreManager.Reset(Thread.CurrentThread); + } + else if (selectedCount == 1) + { + CoreManager.Set(Thread.CurrentThread); + } + else + { + throw new InvalidOperationException("Thread scheduled in more than one core!"); + } + } + else + { + KThread currentThread = CoreContexts[_currentCore].CurrentThread; + + bool hasThreadExecuting = currentThread != null; + + if (hasThreadExecuting) + { + //If this is not the thread that is currently executing, we need + //to request an interrupt to allow safely starting another thread. + if (!currentThread.Context.IsCurrentThread()) + { + currentThread.Context.RequestInterrupt(); + + return; + } + + CoreManager.Reset(currentThread.Context.Work); + } + + //Advance current core and try picking a thread, + //keep advancing if it is null. + for (int core = 0; core < 4; core++) + { + _currentCore = (_currentCore + 1) % CpuCoresCount; + + KCoreContext coreContext = CoreContexts[_currentCore]; + + coreContext.UpdateCurrentThread(); + + if (coreContext.CurrentThread != null) + { + coreContext.CurrentThread.ClearExclusive(); + + CoreManager.Set(coreContext.CurrentThread.Context.Work); + + coreContext.CurrentThread.Context.Execute(); + + break; + } + } + + //If nothing was running before, then we are on a "external" + //HLE thread, we don't need to wait. + if (!hasThreadExecuting) + { + return; + } + } + } + + CoreManager.Wait(Thread.CurrentThread); + } + + private void PreemptCurrentThread() + { + //Preempts current thread every 10 milliseconds on a round-robin fashion, + //when multi core scheduling is disabled, to try ensuring that all threads + //gets a chance to run. + while (_keepPreempting) + { + lock (CoreContexts) + { + KThread currentThread = CoreContexts[_currentCore].CurrentThread; + + currentThread?.Context.RequestInterrupt(); + } + + PreemptThreads(); + + Thread.Sleep(RoundRobinTimeQuantumMs); + } + } + + public void ExitThread(KThread thread) + { + thread.Context.StopExecution(); + + CoreManager.Exit(thread.Context.Work); + } + + public void RemoveThread(KThread thread) + { + CoreManager.RemoveThread(thread.Context.Work); + } + } +}
\ No newline at end of file |