Remove _idleThread entirely
This commit is contained in:
parent
c0c81d4c9d
commit
83f2eb9495
3 changed files with 26 additions and 52 deletions
|
@ -31,35 +31,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
private KThread _previousThread;
|
private KThread _previousThread;
|
||||||
private KThread _currentThread;
|
private KThread _currentThread;
|
||||||
private readonly KThread _idleThread;
|
|
||||||
|
|
||||||
private int _coreIdleLock;
|
private int _coreIdleLock;
|
||||||
private bool _idleSignalled = true;
|
private bool _idleSignalled = true;
|
||||||
private bool _idleActive = true;
|
private bool _idleActive = true;
|
||||||
|
private long _idleTimeRunning;
|
||||||
|
|
||||||
public KThread PreviousThread => _previousThread;
|
public KThread PreviousThread => _previousThread;
|
||||||
public KThread CurrentThread => _currentThread;
|
public KThread CurrentThread => _currentThread;
|
||||||
public long LastContextSwitchTime { get; private set; }
|
public long LastContextSwitchTime { get; private set; }
|
||||||
public long TotalIdleTimeTicks => _idleThread.TotalTimeRunning;
|
public long TotalIdleTimeTicks => _idleTimeRunning;
|
||||||
|
|
||||||
public KScheduler(KernelContext context, int coreId)
|
public KScheduler(KernelContext context, int coreId)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_coreId = coreId;
|
_coreId = coreId;
|
||||||
|
|
||||||
KThread idleThread = CreateIdleThread(context, coreId);
|
_currentThread = null;
|
||||||
|
|
||||||
_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong SelectThreads(KernelContext context)
|
public static ulong SelectThreads(KernelContext context)
|
||||||
|
@ -233,7 +221,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KThread threadToSignal = context.Schedulers[coreToSignal]._currentThread;
|
KThread threadToSignal = context.Schedulers[coreToSignal]._currentThread;
|
||||||
|
|
||||||
// Request the thread running on that core to stop and reschedule, if we have one.
|
// 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();
|
threadToSignal.Context.RequestInterrupt();
|
||||||
}
|
}
|
||||||
|
@ -281,9 +269,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
_state.NeedsScheduling = false;
|
_state.NeedsScheduling = false;
|
||||||
Thread.MemoryBarrier();
|
Thread.MemoryBarrier();
|
||||||
KThread nextThread = PickNextThread(_idleThread, _state.SelectedThread);
|
KThread nextThread = PickNextThread(null, _state.SelectedThread);
|
||||||
|
|
||||||
if (_idleThread != nextThread)
|
if (nextThread != null)
|
||||||
{
|
{
|
||||||
_idleActive = false;
|
_idleActive = false;
|
||||||
nextThread.SchedulerWaitEvent.Set();
|
nextThread.SchedulerWaitEvent.Set();
|
||||||
|
@ -306,7 +294,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(currentThread != _idleThread);
|
Debug.Assert(currentThread != null);
|
||||||
|
|
||||||
currentThread.SchedulerWaitEvent.Reset();
|
currentThread.SchedulerWaitEvent.Reset();
|
||||||
currentThread.ThreadContext.Unlock();
|
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.
|
// Wait until this thread is scheduled again, and allow the next thread to run.
|
||||||
|
|
||||||
if (nextThread == _idleThread)
|
if (nextThread == null)
|
||||||
{
|
{
|
||||||
ActivateIdleThread();
|
ActivateIdleThread();
|
||||||
currentThread.SchedulerWaitEvent.WaitOne();
|
currentThread.SchedulerWaitEvent.WaitOne();
|
||||||
|
@ -337,7 +325,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
// Allow the next thread to run.
|
// Allow the next thread to run.
|
||||||
|
|
||||||
if (nextThread == _idleThread)
|
if (nextThread == null)
|
||||||
{
|
{
|
||||||
ActivateIdleThread();
|
ActivateIdleThread();
|
||||||
}
|
}
|
||||||
|
@ -385,7 +373,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return _idleThread;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -393,7 +381,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
// The core is idle now, make sure that the idle thread can run
|
// The core is idle now, make sure that the idle thread can run
|
||||||
// and switch the core when a thread is available.
|
// and switch the core when a thread is available.
|
||||||
SwitchTo(currentThread, null);
|
SwitchTo(currentThread, null);
|
||||||
return _idleThread;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_state.NeedsScheduling = false;
|
_state.NeedsScheduling = false;
|
||||||
|
@ -404,9 +392,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
private void SwitchTo(KThread currentThread, KThread nextThread)
|
private void SwitchTo(KThread currentThread, KThread nextThread)
|
||||||
{
|
{
|
||||||
KProcess currentProcess = currentThread.Owner;
|
KProcess currentProcess = currentThread?.Owner;
|
||||||
|
|
||||||
nextThread ??= _idleThread;
|
|
||||||
|
|
||||||
if (currentThread != nextThread)
|
if (currentThread != nextThread)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +400,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
long currentTicks = PerformanceCounter.ElapsedTicks;
|
long currentTicks = PerformanceCounter.ElapsedTicks;
|
||||||
long ticksDelta = currentTicks - previousTicks;
|
long ticksDelta = currentTicks - previousTicks;
|
||||||
|
|
||||||
currentThread.AddCpuTime(ticksDelta);
|
if (currentThread == null)
|
||||||
|
{
|
||||||
|
Interlocked.Add(ref _idleTimeRunning, ticksDelta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentThread.AddCpuTime(ticksDelta);
|
||||||
|
}
|
||||||
|
|
||||||
currentProcess?.AddCpuTime(ticksDelta);
|
currentProcess?.AddCpuTime(ticksDelta);
|
||||||
|
|
||||||
|
@ -424,13 +417,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
_previousThread = !currentThread.TerminationRequested && currentThread.ActiveCore == _coreId ? currentThread : null;
|
_previousThread = !currentThread.TerminationRequested && currentThread.ActiveCore == _coreId ? currentThread : null;
|
||||||
}
|
}
|
||||||
else if (currentThread == _idleThread)
|
else if (currentThread == null)
|
||||||
{
|
{
|
||||||
_previousThread = null;
|
_previousThread = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextThread.CurrentCore != _coreId)
|
if (nextThread != null && nextThread.CurrentCore != _coreId)
|
||||||
{
|
{
|
||||||
nextThread.CurrentCore = _coreId;
|
nextThread.CurrentCore = _coreId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
private ulong _entrypoint;
|
private ulong _entrypoint;
|
||||||
private ThreadStart _customThreadStart;
|
private ThreadStart _customThreadStart;
|
||||||
private bool _forcedUnschedulable;
|
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 ulong MutexAddress { get; set; }
|
||||||
public int KernelWaitersCount { get; private set; }
|
public int KernelWaitersCount { get; private set; }
|
||||||
|
@ -145,11 +144,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
PreferredCore = cpuCore;
|
PreferredCore = cpuCore;
|
||||||
AffinityMask |= 1UL << cpuCore;
|
AffinityMask |= 1UL << cpuCore;
|
||||||
|
|
||||||
_isDummy = type == ThreadType.Dummy;
|
SchedFlags = ThreadSchedState.None;
|
||||||
|
|
||||||
SchedFlags = _isDummy
|
|
||||||
? ThreadSchedState.Running
|
|
||||||
: ThreadSchedState.None;
|
|
||||||
|
|
||||||
ActiveCore = cpuCore;
|
ActiveCore = cpuCore;
|
||||||
ObjSyncResult = KernelResult.ThreadNotStarted;
|
ObjSyncResult = KernelResult.ThreadNotStarted;
|
||||||
|
@ -187,10 +182,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
is64Bits = true;
|
is64Bits = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_isDummy)
|
HostThread = new Thread(ThreadStart);
|
||||||
{
|
|
||||||
HostThread = new Thread(ThreadStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
||||||
|
|
||||||
|
@ -214,10 +206,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
ThreadUid = KernelContext.NewThreadUid();
|
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;
|
_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
|
// it directly as we don't care about priority or the core it is
|
||||||
// running on in this case.
|
// running on in this case.
|
||||||
|
|
||||||
Debug.Assert(!_isDummy);
|
|
||||||
|
|
||||||
if (SchedFlags == ThreadSchedState.Running)
|
if (SchedFlags == ThreadSchedState.Running)
|
||||||
{
|
{
|
||||||
_schedulerWaitEvent.Set();
|
_schedulerWaitEvent.Set();
|
||||||
|
@ -1244,11 +1231,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
public void StartHostThread()
|
public void StartHostThread()
|
||||||
{
|
{
|
||||||
if (_isDummy)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Dummy threads can't start a host thread.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_schedulerWaitEvent == null)
|
if (_schedulerWaitEvent == null)
|
||||||
{
|
{
|
||||||
var schedulerWaitEvent = new ManualResetEvent(false);
|
var schedulerWaitEvent = new ManualResetEvent(false);
|
||||||
|
|
|
@ -2,7 +2,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
enum ThreadType
|
enum ThreadType
|
||||||
{
|
{
|
||||||
Dummy,
|
|
||||||
Kernel,
|
Kernel,
|
||||||
Kernel2,
|
Kernel2,
|
||||||
User,
|
User,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue