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/Common | |
| 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/Common')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs | 15 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs | 87 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs | 10 |
3 files changed, 54 insertions, 58 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs b/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs index 812cbd30..a94b280f 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using System.Threading; namespace Ryujinx.HLE.HOS.Kernel.Common @@ -47,17 +48,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Common public void IncrementReferenceCount() { - Interlocked.Increment(ref _referenceCount); + int newRefCount = Interlocked.Increment(ref _referenceCount); + + Debug.Assert(newRefCount >= 2); } public void DecrementReferenceCount() { - if (Interlocked.Decrement(ref _referenceCount) == 0) + int newRefCount = Interlocked.Decrement(ref _referenceCount); + + Debug.Assert(newRefCount >= 0); + + if (newRefCount == 0) { Destroy(); } } - protected virtual void Destroy() { } + protected virtual void Destroy() + { + } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs index 8273520f..f7a1c24a 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs @@ -10,9 +10,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { private class WaitingObject { - public IKFutureSchedulerObject Object { get; private set; } - - public long TimePoint { get; private set; } + public IKFutureSchedulerObject Object { get; } + public long TimePoint { get; } public WaitingObject(IKFutureSchedulerObject schedulerObj, long timePoint) { @@ -21,16 +20,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Common } } - private List<WaitingObject> _waitingObjects; - + private readonly KernelContext _context; + private readonly List<WaitingObject> _waitingObjects; private AutoResetEvent _waitEvent; - private bool _keepRunning; - public KTimeManager() + public KTimeManager(KernelContext context) { + _context = context; _waitingObjects = new List<WaitingObject>(); - _keepRunning = true; Thread work = new Thread(WaitAndCheckScheduledObjects) @@ -45,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { long timePoint = PerformanceCounter.ElapsedMilliseconds + ConvertNanosecondsToMilliseconds(timeout); - lock (_waitingObjects) + lock (_context.CriticalSection.Lock) { _waitingObjects.Add(new WaitingObject(schedulerObj, timePoint)); } @@ -53,33 +51,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Common _waitEvent.Set(); } - public static long ConvertNanosecondsToMilliseconds(long time) - { - time /= 1000000; - - if ((ulong)time > int.MaxValue) - { - return int.MaxValue; - } - - return time; - } - - public static long ConvertMillisecondsToNanoseconds(long time) - { - return time * 1000000; - } - - public static long ConvertMillisecondsToTicks(long time) - { - return time * 19200; - } - - public void UnscheduleFutureInvocation(IKFutureSchedulerObject Object) + public void UnscheduleFutureInvocation(IKFutureSchedulerObject schedulerObj) { - lock (_waitingObjects) + lock (_context.CriticalSection.Lock) { - _waitingObjects.RemoveAll(x => x.Object == Object); + _waitingObjects.RemoveAll(x => x.Object == schedulerObj); } } @@ -91,7 +67,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { WaitingObject next; - lock (_waitingObjects) + lock (_context.CriticalSection.Lock) { next = _waitingObjects.OrderBy(x => x.TimePoint).FirstOrDefault(); } @@ -109,16 +85,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Common if (timeUp) { - lock (_waitingObjects) + lock (_context.CriticalSection.Lock) { - timeUp = _waitingObjects.Remove(next); + if (_waitingObjects.Remove(next)) + { + next.Object.TimeUp(); + } } } - - if (timeUp) - { - next.Object.TimeUp(); - } } else { @@ -128,19 +102,32 @@ namespace Ryujinx.HLE.HOS.Kernel.Common } } - public void Dispose() + public static long ConvertNanosecondsToMilliseconds(long time) + { + time /= 1000000; + + if ((ulong)time > int.MaxValue) + { + return int.MaxValue; + } + + return time; + } + + public static long ConvertMillisecondsToNanoseconds(long time) { - Dispose(true); + return time * 1000000; } - protected virtual void Dispose(bool disposing) + public static long ConvertHostTicksToTicks(long time) { - if (disposing) - { - _keepRunning = false; + return (long)((time / (double)PerformanceCounter.TicksPerSecond) * 19200000.0); + } - _waitEvent?.Set(); - } + public void Dispose() + { + _keepRunning = false; + _waitEvent?.Set(); } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs index d57ca481..3002b6a9 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs @@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { public static bool UserToKernelInt32(KernelContext context, ulong address, out int value) { - KProcess currentProcess = context.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 3)) @@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common public static bool UserToKernelInt32Array(KernelContext context, ulong address, Span<int> values) { - KProcess currentProcess = context.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelStatic.GetCurrentProcess(); for (int index = 0; index < values.Length; index++, address += 4) { @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common public static bool UserToKernelString(KernelContext context, ulong address, int size, out string value) { - KProcess currentProcess = context.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + (ulong)size - 1)) @@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common public static bool KernelToUserInt32(KernelContext context, ulong address, int value) { - KProcess currentProcess = context.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 3)) @@ -77,7 +77,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common public static bool KernelToUserInt64(KernelContext context, ulong address, long value) { - KProcess currentProcess = context.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 7)) |
