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
This commit is contained in:
gdkchan 2020-12-09 19:20:05 -03:00 committed by GitHub
parent 3484265d37
commit 48278905d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 1080 additions and 1160 deletions

View file

@ -19,6 +19,8 @@ namespace Ryujinx.HLE.HOS.Kernel
public bool KernelInitialized { get; }
public bool Running { get; private set; }
public Switch Device { get; }
public MemoryBlock Memory { get; }
public Syscall Syscall { get; }
@ -34,7 +36,8 @@ namespace Ryujinx.HLE.HOS.Kernel
public KSlabHeap UserSlabHeapPages { get; }
public KCriticalSection CriticalSection { get; }
public KScheduler Scheduler { get; }
public KScheduler[] Schedulers { get; }
public KPriorityQueue PriorityQueue { get; }
public KTimeManager TimeManager { get; }
public KSynchronization Synchronization { get; }
public KContextIdManager ContextIdManager { get; }
@ -42,6 +45,8 @@ namespace Ryujinx.HLE.HOS.Kernel
public ConcurrentDictionary<long, KProcess> Processes { get; }
public ConcurrentDictionary<string, KAutoObject> AutoObjectNames { get; }
public bool ThreadReselectionRequested { get; set; }
private long _kipId;
private long _processId;
private long _threadUid;
@ -51,6 +56,8 @@ namespace Ryujinx.HLE.HOS.Kernel
Device = device;
Memory = memory;
Running = true;
Syscall = new Syscall(this);
SyscallHandler = new SyscallHandler(this);
@ -70,12 +77,18 @@ namespace Ryujinx.HLE.HOS.Kernel
KernelConstants.UserSlabHeapSize);
CriticalSection = new KCriticalSection(this);
Scheduler = new KScheduler(this);
TimeManager = new KTimeManager();
Schedulers = new KScheduler[KScheduler.CpuCoresCount];
PriorityQueue = new KPriorityQueue();
TimeManager = new KTimeManager(this);
Synchronization = new KSynchronization(this);
ContextIdManager = new KContextIdManager();
Scheduler.StartAutoPreemptionThread();
for (int core = 0; core < KScheduler.CpuCoresCount; core++)
{
Schedulers[core] = new KScheduler(this, core);
}
StartPreemptionThread();
KernelInitialized = true;
@ -86,6 +99,16 @@ namespace Ryujinx.HLE.HOS.Kernel
_processId = KernelConstants.InitialProcessId;
}
private void StartPreemptionThread()
{
void PreemptionThreadStart()
{
KScheduler.PreemptionThreadLoop(this);
}
new Thread(PreemptionThreadStart) { Name = "HLE.PreemptionThread" }.Start();
}
public long NewThreadUid()
{
return Interlocked.Increment(ref _threadUid) - 1;
@ -103,7 +126,13 @@ namespace Ryujinx.HLE.HOS.Kernel
public void Dispose()
{
Scheduler.Dispose();
Running = false;
for (int i = 0; i < KScheduler.CpuCoresCount; i++)
{
Schedulers[i].Dispose();
}
TimeManager.Dispose();
}
}