[Kernel] Poll host sync waits in bounded slices

Co-authored-by: Sekai <140012992+igettingit@users.noreply.github.com>
This commit is contained in:
ParantezTech 2026-10-06 13:44:49 +03:00
parent 77532c6f79
commit 6d62f8599f
1 changed files with 47 additions and 26 deletions

View File

@ -114,37 +114,41 @@ public static class KernelSyncOnAddressCompatExports
return true;
}
public int WaitOnHost(TimeSpan? timeout)
public int WaitOnHost()
{
if (Volatile.Read(ref _wakeRequested) == 0)
while (Volatile.Read(ref _wakeRequested) == 0)
{
lock (_hostGate)
if (!TryReadValue(_context, Address, _is64Bit, out var current) ||
current != _expected)
{
if (timeout is null)
{
while (Volatile.Read(ref _wakeRequested) == 0)
{
Monitor.Wait(_hostGate);
}
}
else
{
var deadline = Stopwatch.GetTimestamp() +
(long)Math.Ceiling(timeout.Value.TotalSeconds * Stopwatch.Frequency);
while (Volatile.Read(ref _wakeRequested) == 0)
{
var remainingTicks = deadline - Stopwatch.GetTimestamp();
if (remainingTicks <= 0)
{
break;
}
break;
}
var remaining = TimeSpan.FromSeconds(
remainingTicks / (double)Stopwatch.Frequency);
Monitor.Wait(_hostGate, remaining);
}
var waitSlice = TimeSpan.FromMilliseconds(10);
if (_deadlineTimestamp != 0)
{
var remainingTicks = _deadlineTimestamp - Stopwatch.GetTimestamp();
if (remainingTicks <= 0)
{
break;
}
var remainingSeconds = remainingTicks / (double)Stopwatch.Frequency;
if (remainingSeconds < waitSlice.TotalSeconds)
{
waitSlice = TimeSpan.FromSeconds(remainingSeconds);
}
}
lock (_hostGate)
{
if (Volatile.Read(ref _wakeRequested) == 0)
{
Monitor.Wait(_hostGate, waitSlice);
}
}
GuestThreadExecution.Scheduler?.DeliverPendingGuestExceptionIfReady(_context);
}
return Resume();
@ -424,7 +428,24 @@ public static class KernelSyncOnAddressCompatExports
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
}
return SetReturn(ctx, waiter.WaitOnHost(timeout));
return SetReturn(ctx, waiter.WaitOnHost());
}
private static TimeSpan CreateTimespecDuration(long seconds, long nanoseconds)
{
var subsecondTicks = (nanoseconds + 99L) / 100L;
if (seconds > TimeSpan.MaxValue.Ticks / TimeSpan.TicksPerSecond)
{
return TimeSpan.MaxValue;
}
var secondTicks = seconds * TimeSpan.TicksPerSecond;
if (secondTicks > TimeSpan.MaxValue.Ticks - subsecondTicks)
{
return TimeSpan.MaxValue;
}
return TimeSpan.FromTicks(secondTicks + subsecondTicks);
}
private static void Register(ulong address, SyncWaiter waiter)