diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-12-09 19:20:05 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-09 19:20:05 -0300 |
| commit | 48278905d1470f89be31668c738397f569af156a (patch) | |
| tree | 2e35b0695b33c8eb723f5948e3f6f040d84cfe76 /Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs | |
| parent | 3484265d37732b32951709e5abfa52a260db349d (diff) | |
Rewrite scheduler context switch code (#1786)
* Rewrite scheduler context switch code
* Fix race in UnmapIpcRestorePermission
* Fix thread exit issue that could leave the scheduler in a invalid state
* Change context switch method to not wait on guest thread, remove spin wait, use SignalAndWait to pass control
* Remove multi-core setting (it is always on now)
* Re-enable assert
* Remove multicore from default config and schema
* Fix race in KTimeManager
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs | 70 |
1 files changed, 21 insertions, 49 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs index b778c2a4..1d61f2f0 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs @@ -5,21 +5,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading class KCriticalSection { private readonly KernelContext _context; - - public object LockObj { get; private set; } - + private readonly object _lock; private int _recursionCount; + public object Lock => _lock; + public KCriticalSection(KernelContext context) { _context = context; - - LockObj = new object(); + _lock = new object(); } public void Enter() { - Monitor.Enter(LockObj); + Monitor.Enter(_lock); _recursionCount++; } @@ -31,61 +30,34 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return; } - bool doContextSwitch = false; - if (--_recursionCount == 0) { - if (_context.Scheduler.ThreadReselectionRequested) - { - _context.Scheduler.SelectThreads(); - } + ulong scheduledCoresMask = KScheduler.SelectThreads(_context); - Monitor.Exit(LockObj); + Monitor.Exit(_lock); - if (_context.Scheduler.MultiCoreScheduling) + KThread currentThread = KernelStatic.GetCurrentThread(); + bool isCurrentThreadSchedulable = currentThread != null && currentThread.IsSchedulable; + if (isCurrentThreadSchedulable) { - lock (_context.Scheduler.CoreContexts) - { - for (int core = 0; core < KScheduler.CpuCoresCount; core++) - { - KCoreContext coreContext = _context.Scheduler.CoreContexts[core]; - - if (coreContext.ContextSwitchNeeded) - { - KThread currentThread = coreContext.CurrentThread; - - if (currentThread == null) - { - // Nothing is running, we can perform the context switch immediately. - coreContext.ContextSwitch(); - } - else if (currentThread.IsCurrentHostThread()) - { - // Thread running on the current core, context switch will block. - doContextSwitch = true; - } - else - { - // Thread running on another core, request a interrupt. - currentThread.Context.RequestInterrupt(); - } - } - } - } + KScheduler.EnableScheduling(_context, scheduledCoresMask); } else { - doContextSwitch = true; + KScheduler.EnableSchedulingFromForeignThread(_context, scheduledCoresMask); + + // If the thread exists but is not schedulable, we still want to suspend + // it if it's not runnable. That allows the kernel to still block HLE threads + // even if they are not scheduled on guest cores. + if (currentThread != null && !currentThread.IsSchedulable && currentThread.Context.Running) + { + currentThread.SchedulerWaitEvent.WaitOne(); + } } } else { - Monitor.Exit(LockObj); - } - - if (doContextSwitch) - { - _context.Scheduler.ContextSwitch(); + Monitor.Exit(_lock); } } } |
