[CPU] Preserve blocked leaf import waiters (#350)

This commit is contained in:
Peter Bonanni
2026-07-17 19:59:13 -04:00
committed by GitHub
parent c9d018db8e
commit 0b1dea43e8
4 changed files with 126 additions and 85 deletions
@@ -1345,8 +1345,7 @@ public sealed partial class DirectExecutionBackend
out var blockContinuation,
out var hasBlockContinuation,
out var blockWakeKey,
out var blockResumeHandler,
out var blockWakeHandler,
out var blockWaiter,
out var blockDeadlineTimestamp);
if (consumedThreadBlock &&
TryYieldGuestThreadToHostStub(argPackPtr, dispatchIndex, returnRip, importStubEntry.Nid, blockReason))
@@ -1357,8 +1356,7 @@ public sealed partial class DirectExecutionBackend
GuestThreadExecution.CurrentGuestThreadHandle,
blockContinuation,
blockWakeKey,
blockResumeHandler,
blockWakeHandler,
blockWaiter,
blockDeadlineTimestamp);
}
@@ -443,10 +443,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
// Stays set through the wake transition; Resume() consumes it when the thread pumps.
public IGuestThreadBlockWaiter? BlockWaiter { get; set; }
public Func<int>? BlockResumeHandler { get; set; }
public Func<bool>? BlockWakeHandler { get; set; }
public long BlockDeadlineTimestamp { get; set; }
public long ImportCount;
@@ -3215,43 +3211,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
thread.HasBlockedContinuation = true;
thread.BlockWakeKey = wakeKey;
thread.BlockWaiter = waiter;
thread.BlockResumeHandler = null;
thread.BlockWakeHandler = null;
thread.BlockDeadlineTimestamp = blockDeadlineTimestamp;
TraceFocusedContinuation(
"register",
guestThreadHandle,
continuation,
wakeKey);
}
}
private void RegisterBlockedGuestThreadContinuation(
ulong guestThreadHandle,
GuestCpuContinuation continuation,
string wakeKey,
Func<int>? resumeHandler,
Func<bool>? wakeHandler,
long blockDeadlineTimestamp)
{
if (guestThreadHandle == 0 || continuation.Rip < 65536 || continuation.Rsp == 0)
{
return;
}
using (LockGate("RegisterBlockedContinuation"))
{
if (!_guestThreads.TryGetValue(guestThreadHandle, out var thread))
{
return;
}
thread.BlockedContinuation = continuation;
thread.HasBlockedContinuation = true;
thread.BlockWakeKey = wakeKey;
thread.BlockWaiter = null;
thread.BlockResumeHandler = resumeHandler;
thread.BlockWakeHandler = wakeHandler;
thread.BlockDeadlineTimestamp = blockDeadlineTimestamp;
TraceFocusedContinuation(
"register",
@@ -3567,11 +3526,10 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
owner.State = GuestThreadRunState.Blocked;
owner.BlockReason = callbackReason ?? reason;
if (owner.BlockWakeHandler is not null && owner.BlockWakeHandler())
if (owner.BlockWaiter is not null && owner.BlockWaiter.TryWake())
{
owner.State = GuestThreadRunState.Ready;
owner.BlockReason = null;
owner.BlockWakeHandler = null;
owner.BlockDeadlineTimestamp = 0;
}
}
@@ -3583,7 +3541,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
}
GuestCpuContinuation continuation = default;
Func<int>? resumeHandler = null;
IGuestThreadBlockWaiter? blockWaiter = null;
while (!ActiveForcedGuestExit)
{
WakeExpiredBlockedGuestThreads();
@@ -3604,9 +3562,8 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
owner.BlockedContinuation = default;
owner.HasBlockedContinuation = false;
owner.BlockWakeKey = null;
resumeHandler = owner.BlockResumeHandler;
owner.BlockResumeHandler = null;
owner.BlockWakeHandler = null;
blockWaiter = owner.BlockWaiter;
owner.BlockWaiter = null;
owner.BlockDeadlineTimestamp = 0;
owner.BlockReason = null;
owner.State = GuestThreadRunState.Running;
@@ -3629,9 +3586,9 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
return false;
}
if (resumeHandler is not null)
if (blockWaiter is not null)
{
continuation = continuation with { Rax = unchecked((ulong)(long)resumeHandler()) };
continuation = continuation with { Rax = unchecked((ulong)(long)blockWaiter.Resume()) };
}
if (_logGuestThreads)
{
@@ -3844,8 +3801,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
bool savedHasBlockedContinuation;
GuestCpuContinuation savedBlockedContinuation;
string? savedBlockWakeKey;
Func<int>? savedBlockResumeHandler;
Func<bool>? savedBlockWakeHandler;
IGuestThreadBlockWaiter? savedBlockWaiter;
long savedBlockDeadlineTimestamp;
ulong exceptionStackBase;
lock (_guestThreadGate)
@@ -3981,8 +3937,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
savedHasBlockedContinuation = target.HasBlockedContinuation;
savedBlockedContinuation = target.BlockedContinuation;
savedBlockWakeKey = target.BlockWakeKey;
savedBlockResumeHandler = target.BlockResumeHandler;
savedBlockWakeHandler = target.BlockWakeHandler;
savedBlockWaiter = target.BlockWaiter;
savedBlockDeadlineTimestamp = target.BlockDeadlineTimestamp;
target.State = GuestThreadRunState.Running;
@@ -3992,8 +3947,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
target.HasBlockedContinuation = false;
target.BlockedContinuation = default;
target.BlockWakeKey = null;
target.BlockResumeHandler = null;
target.BlockWakeHandler = null;
target.BlockWaiter = null;
target.BlockDeadlineTimestamp = 0;
}
@@ -4041,8 +3995,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
target.HasBlockedContinuation = savedHasBlockedContinuation;
target.BlockedContinuation = savedBlockedContinuation;
target.BlockWakeKey = savedBlockWakeKey;
target.BlockResumeHandler = savedBlockResumeHandler;
target.BlockWakeHandler = savedBlockWakeHandler;
target.BlockWaiter = savedBlockWaiter;
target.BlockDeadlineTimestamp = savedBlockDeadlineTimestamp;
// A condition/event wake can arrive while the parked thread is
@@ -4052,12 +4005,11 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
// pthread wait remains parked forever after a GC suspension races it.
if (target.State == GuestThreadRunState.Blocked &&
target.HasBlockedContinuation &&
target.BlockWakeHandler is not null &&
target.BlockWakeHandler())
target.BlockWaiter is not null &&
target.BlockWaiter.TryWake())
{
target.State = GuestThreadRunState.Ready;
target.BlockReason = null;
target.BlockWakeHandler = null;
target.BlockDeadlineTimestamp = 0;
_readyGuestThreads.Enqueue(target);
Interlocked.Increment(ref _readyGuestThreadCount);
-21
View File
@@ -398,27 +398,6 @@ public static class GuestThreadExecution
return true;
}
public static bool TryConsumeCurrentThreadBlock(
out string reason,
out GuestCpuContinuation continuation,
out bool hasContinuation,
out string wakeKey,
out Func<int>? resumeHandler,
out Func<bool>? wakeHandler,
out long blockDeadlineTimestamp)
{
var consumed = TryConsumeCurrentThreadBlock(
out reason,
out continuation,
out hasContinuation,
out wakeKey,
out var waiter,
out blockDeadlineTimestamp);
resumeHandler = waiter is null ? null : waiter.Resume;
wakeHandler = waiter is null ? null : waiter.TryWake;
return consumed;
}
public static long ComputeDeadlineTimestamp(TimeSpan timeout)
{
if (timeout <= TimeSpan.Zero)