aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-11-30 10:39:42 -0800
committerGitHub <noreply@github.com>2023-11-30 15:39:42 -0300
commit1be668e68a1937f2af239e2707ab914286018892 (patch)
treed3ecb590d444ab9b392928ae1e223930313615e6 /src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
parent21cd4c0c00e4a06e399c93419c8f9eff0e663bfb (diff)
HLE: Add OS-specific precise sleep methods to reduce spinwaiting (#5948)1.1.1094
* feat: add nanosleep for linux and macos * Add Windows 0.5ms sleep - Imprecise waits for longer waits with clock alignment - 1/4 the spin time on vsync timer * Remove old experiment * Fix event leak * Tweaking for MacOS * Linux tweaks, nanosleep vsync improvement * Fix overbias * Cleanup * Fix realignment * Add some docs and some cleanup NanosleepPool needs more, Nanosleep has some benchmark code that needs removed. * Rename "Microsleep" to "PreciseSleep" Might have been confused with "microseconds", which no measurement is performed in. * Remove nanosleep measurement * Remove unused debug logging * Nanosleep Pool Documentation * More cleanup * Whitespace * Formatting * Address Feedback * Allow SleepUntilTimePoint to take EventWaitHandle * Remove `_chrono` stopwatch in SurfaceFlinger * Move spinwaiting logic to PreciseSleepHelper Technically, these achieve different things, but having them here makes them easier to reuse or tune.
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs')
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs39
1 files changed, 10 insertions, 29 deletions
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs b/src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
index 499bc2c6..3c5fa067 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
@@ -1,4 +1,5 @@
using Ryujinx.Common;
+using Ryujinx.Common.PreciseSleep;
using System;
using System.Collections.Generic;
using System.Threading;
@@ -23,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
private readonly KernelContext _context;
private readonly List<WaitingObject> _waitingObjects;
- private AutoResetEvent _waitEvent;
+ private IPreciseSleepEvent _waitEvent;
private bool _keepRunning;
private long _enforceWakeupFromSpinWait;
@@ -54,6 +55,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
timePoint = long.MaxValue;
}
+ timePoint = _waitEvent.AdjustTimePoint(timePoint, timeout);
+
lock (_context.CriticalSection.Lock)
{
_waitingObjects.Add(new WaitingObject(schedulerObj, timePoint));
@@ -64,7 +67,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
}
}
- _waitEvent.Set();
+ _waitEvent.Signal();
}
public void UnscheduleFutureInvocation(IKFutureSchedulerObject schedulerObj)
@@ -83,10 +86,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
private void WaitAndCheckScheduledObjects()
{
- SpinWait spinWait = new();
WaitingObject next;
- using (_waitEvent = new AutoResetEvent(false))
+ using (_waitEvent = PreciseSleepHelper.CreateEvent())
{
while (_keepRunning)
{
@@ -103,30 +105,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
if (next.TimePoint > timePoint)
{
- long ms = Math.Min((next.TimePoint - timePoint) / PerformanceCounter.TicksPerMillisecond, int.MaxValue);
-
- if (ms > 0)
- {
- _waitEvent.WaitOne((int)ms);
- }
- else
+ if (!_waitEvent.SleepUntil(next.TimePoint))
{
- while (Interlocked.Read(ref _enforceWakeupFromSpinWait) != 1 && PerformanceCounter.ElapsedTicks < next.TimePoint)
- {
- // Our time is close - don't let SpinWait go off and potentially Thread.Sleep().
- if (spinWait.NextSpinWillYield)
- {
- Thread.Yield();
-
- spinWait.Reset();
- }
- else
- {
- spinWait.SpinOnce();
- }
- }
-
- spinWait.Reset();
+ PreciseSleepHelper.SpinWaitUntilTimePoint(next.TimePoint, ref _enforceWakeupFromSpinWait);
}
}
@@ -145,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
}
else
{
- _waitEvent.WaitOne();
+ _waitEvent.Sleep();
}
}
}
@@ -212,7 +193,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
public void Dispose()
{
_keepRunning = false;
- _waitEvent?.Set();
+ _waitEvent?.Signal();
}
}
}