From 83f2eb9495fc845dec84faaa50374a065d763b7b Mon Sep 17 00:00:00 2001 From: riperiperi Date: Mon, 20 May 2024 19:36:59 +0100 Subject: [PATCH] Remove _idleThread entirely --- .../HOS/Kernel/Threading/KScheduler.cs | 51 ++++++++----------- .../HOS/Kernel/Threading/KThread.cs | 26 ++-------- .../HOS/Kernel/Threading/ThreadType.cs | 1 - 3 files changed, 26 insertions(+), 52 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index 6d7d13ec70..eddca10a5f 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -31,35 +31,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private KThread _previousThread; private KThread _currentThread; - private readonly KThread _idleThread; private int _coreIdleLock; private bool _idleSignalled = true; private bool _idleActive = true; + private long _idleTimeRunning; public KThread PreviousThread => _previousThread; public KThread CurrentThread => _currentThread; public long LastContextSwitchTime { get; private set; } - public long TotalIdleTimeTicks => _idleThread.TotalTimeRunning; + public long TotalIdleTimeTicks => _idleTimeRunning; public KScheduler(KernelContext context, int coreId) { _context = context; _coreId = coreId; - KThread idleThread = CreateIdleThread(context, coreId); - - _currentThread = idleThread; - _idleThread = idleThread; - } - - private KThread CreateIdleThread(KernelContext context, int cpuCore) - { - KThread idleThread = new(context); - - idleThread.Initialize(0UL, 0UL, 0UL, PrioritiesCount, cpuCore, null, ThreadType.Dummy, null); - - return idleThread; + _currentThread = null; } public static ulong SelectThreads(KernelContext context) @@ -233,7 +221,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KThread threadToSignal = context.Schedulers[coreToSignal]._currentThread; // Request the thread running on that core to stop and reschedule, if we have one. - if (threadToSignal != context.Schedulers[coreToSignal]._idleThread) + if (threadToSignal != null) { threadToSignal.Context.RequestInterrupt(); } @@ -281,9 +269,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { _state.NeedsScheduling = false; Thread.MemoryBarrier(); - KThread nextThread = PickNextThread(_idleThread, _state.SelectedThread); + KThread nextThread = PickNextThread(null, _state.SelectedThread); - if (_idleThread != nextThread) + if (nextThread != null) { _idleActive = false; nextThread.SchedulerWaitEvent.Set(); @@ -306,7 +294,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return; } - Debug.Assert(currentThread != _idleThread); + Debug.Assert(currentThread != null); currentThread.SchedulerWaitEvent.Reset(); currentThread.ThreadContext.Unlock(); @@ -323,7 +311,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { // Wait until this thread is scheduled again, and allow the next thread to run. - if (nextThread == _idleThread) + if (nextThread == null) { ActivateIdleThread(); currentThread.SchedulerWaitEvent.WaitOne(); @@ -337,7 +325,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { // Allow the next thread to run. - if (nextThread == _idleThread) + if (nextThread == null) { ActivateIdleThread(); } @@ -385,7 +373,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } else { - return _idleThread; + return null; } } else @@ -393,7 +381,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // The core is idle now, make sure that the idle thread can run // and switch the core when a thread is available. SwitchTo(currentThread, null); - return _idleThread; + return null; } _state.NeedsScheduling = false; @@ -404,9 +392,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private void SwitchTo(KThread currentThread, KThread nextThread) { - KProcess currentProcess = currentThread.Owner; - - nextThread ??= _idleThread; + KProcess currentProcess = currentThread?.Owner; if (currentThread != nextThread) { @@ -414,7 +400,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading long currentTicks = PerformanceCounter.ElapsedTicks; long ticksDelta = currentTicks - previousTicks; - currentThread.AddCpuTime(ticksDelta); + if (currentThread == null) + { + Interlocked.Add(ref _idleTimeRunning, ticksDelta); + } + else + { + currentThread.AddCpuTime(ticksDelta); + } currentProcess?.AddCpuTime(ticksDelta); @@ -424,13 +417,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { _previousThread = !currentThread.TerminationRequested && currentThread.ActiveCore == _coreId ? currentThread : null; } - else if (currentThread == _idleThread) + else if (currentThread == null) { _previousThread = null; } } - if (nextThread.CurrentCore != _coreId) + if (nextThread != null && nextThread.CurrentCore != _coreId) { nextThread.CurrentCore = _coreId; } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 4e60e7747d..30079b2967 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -45,9 +45,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private ulong _entrypoint; private ThreadStart _customThreadStart; private bool _forcedUnschedulable; - private bool _isDummy; - public bool IsSchedulable => _customThreadStart == null && !_isDummy && !_forcedUnschedulable; + public bool IsSchedulable => _customThreadStart == null && !_forcedUnschedulable; public ulong MutexAddress { get; set; } public int KernelWaitersCount { get; private set; } @@ -145,11 +144,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading PreferredCore = cpuCore; AffinityMask |= 1UL << cpuCore; - _isDummy = type == ThreadType.Dummy; - - SchedFlags = _isDummy - ? ThreadSchedState.Running - : ThreadSchedState.None; + SchedFlags = ThreadSchedState.None; ActiveCore = cpuCore; ObjSyncResult = KernelResult.ThreadNotStarted; @@ -187,10 +182,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading is64Bits = true; } - if (!_isDummy) - { - HostThread = new Thread(ThreadStart); - } + HostThread = new Thread(ThreadStart); Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext(); @@ -214,10 +206,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ThreadUid = KernelContext.NewThreadUid(); - if (!_isDummy) - { - HostThread.Name = customThreadStart != null ? $"HLE.OsThread.{ThreadUid}" : $"HLE.GuestThread.{ThreadUid}"; - } + HostThread.Name = customThreadStart != null ? $"HLE.OsThread.{ThreadUid}" : $"HLE.GuestThread.{ThreadUid}"; _hasBeenInitialized = true; @@ -1066,8 +1055,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // it directly as we don't care about priority or the core it is // running on in this case. - Debug.Assert(!_isDummy); - if (SchedFlags == ThreadSchedState.Running) { _schedulerWaitEvent.Set(); @@ -1244,11 +1231,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public void StartHostThread() { - if (_isDummy) - { - throw new InvalidOperationException("Dummy threads can't start a host thread."); - } - if (_schedulerWaitEvent == null) { var schedulerWaitEvent = new ManualResetEvent(false); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs index 83093570b7..e2dfd2ffbb 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs @@ -2,7 +2,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { enum ThreadType { - Dummy, Kernel, Kernel2, User,