authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-30 00:44:08+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 12:10:02-08:00
log1a0fa1fa7629d67250df5337948fa1dbf6cdb7ad
tree08fcc3971daa39a1d13583342ec9398a272c6e4a
parent4e198dc1872253533a63468668d9b49a4a9d31dd

std.Io.Threaded: fix ntdll timeouts on Windows


1 files changed, 28 insertions(+), 13 deletions(-)

lib/std/Io/Threaded.zig+28-13
......@@ -2719,7 +2719,13 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa
27192719 }
27202720 }
27212721
2722 var delay_interval: windows.LARGE_INTEGER = timeoutToWindowsInterval(timeout);
2722 const deadline: ?Io.Clock.Timestamp = timeout.toDeadline(ioBasic(t)) catch |err| switch (err) {
2723 error.Unexpected => deadline: {
2724 recoverableOsBugDetected();
2725 break :deadline .{ .raw = .{ .nanoseconds = 0 }, .clock = .awake };
2726 },
2727 error.UnsupportedClock => |e| return e,
2728 };
27232729
27242730 while (true) {
27252731 var any_pending = false;
......@@ -2741,6 +2747,16 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa
27412747 }
27422748 if (b.user.complete_head != complete_tail) return;
27432749 if (!any_pending) return;
2750 var delay_interval: windows.LARGE_INTEGER = interval: {
2751 const d = deadline orelse break :interval std.math.minInt(windows.LARGE_INTEGER);
2752 break :interval t.deadlineToWindowsInterval(d) catch |err| switch (err) {
2753 error.UnsupportedClock => |e| return e,
2754 error.Unexpected => {
2755 recoverableOsBugDetected();
2756 break :interval -1;
2757 },
2758 };
2759 };
27442760 const alertable_syscall = try AlertableSyscall.start();
27452761 const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval);
27462762 alertable_syscall.finish();
......@@ -16784,19 +16800,18 @@ fn park(opt_deadline: ?Io.Clock.Timestamp, addr_hint: ?*const anyopaque) error{T
1678416800 }
1678516801}
1678616802
16787fn timeoutToWindowsInterval(timeout: Io.Timeout) windows.LARGE_INTEGER {
16788 switch (timeout) {
16789 .none => {
16790 return std.math.minInt(windows.LARGE_INTEGER); // infinite timeout
16791 },
16792 .deadline => |deadline| {
16793 const nanoseconds = deadline.raw.nanoseconds;
16794 return @intCast(@divTrunc(nanoseconds, 100));
16803fn deadlineToWindowsInterval(t: *Io.Threaded, deadline: Io.Clock.Timestamp) Io.Clock.Error!windows.LARGE_INTEGER {
16804 // ntdll only supports two combinations:
16805 // * real-time (`.real`) sleeps with absolute deadlines
16806 // * monotonic (`.awake`/`.boot`) sleeps with relative durations
16807 switch (deadline.clock) {
16808 .cpu_process, .cpu_thread => unreachable, // cannot sleep for CPU time
16809 .real => {
16810 return @intCast(@max(@divTrunc(deadline.raw.nanoseconds, 100), 0));
1679516811 },
16796 .duration => |duration| {
16797 const now_timestamp = nowWindows(duration.clock) catch unreachable;
16798 const deadline_ns = now_timestamp.nanoseconds + duration.raw.nanoseconds;
16799 return @intCast(@divTrunc(deadline_ns, 100));
16812 .awake, .boot => {
16813 const duration = try deadline.durationFromNow(ioBasic(t));
16814 return @intCast(@min(@divTrunc(-duration.raw.nanoseconds, 100), -1));
1680016815 },
1680116816 }
1680216817}