Remove _idleThread entirely

This commit is contained in:
riperiperi 2024-05-20 19:36:59 +01:00
parent c0c81d4c9d
commit 83f2eb9495
3 changed files with 26 additions and 52 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -2,7 +2,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
enum ThreadType
{
Dummy,
Kernel,
Kernel2,
User,