aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/Common
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-12-09 19:20:05 -0300
committerGitHub <noreply@github.com>2020-12-09 19:20:05 -0300
commit48278905d1470f89be31668c738397f569af156a (patch)
tree2e35b0695b33c8eb723f5948e3f6f040d84cfe76 /Ryujinx.HLE/HOS/Kernel/Common
parent3484265d37732b32951709e5abfa52a260db349d (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.cs15
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs87
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs10
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))