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...@@ -2719,7 +2719,13 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa
2719 }2719 }
2720 }2720 }
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
2724 while (true) {2730 while (true) {
2725 var any_pending = false;2731 var any_pending = false;
...@@ -2741,6 +2747,16 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa...@@ -2741,6 +2747,16 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa
2741 }2747 }
2742 if (b.user.complete_head != complete_tail) return;2748 if (b.user.complete_head != complete_tail) return;
2743 if (!any_pending) return;2749 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 };
2744 const alertable_syscall = try AlertableSyscall.start();2760 const alertable_syscall = try AlertableSyscall.start();
2745 const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval);2761 const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval);
2746 alertable_syscall.finish();2762 alertable_syscall.finish();
...@@ -16784,19 +16800,18 @@ fn park(opt_deadline: ?Io.Clock.Timestamp, addr_hint: ?*const anyopaque) error{T...@@ -16784,19 +16800,18 @@ fn park(opt_deadline: ?Io.Clock.Timestamp, addr_hint: ?*const anyopaque) error{T
16784 }16800 }
16785}16801}
1678616802
16787fn timeoutToWindowsInterval(timeout: Io.Timeout) windows.LARGE_INTEGER {16803fn deadlineToWindowsInterval(t: *Io.Threaded, deadline: Io.Clock.Timestamp) Io.Clock.Error!windows.LARGE_INTEGER {
16788 switch (timeout) {16804 // ntdll only supports two combinations:
16789 .none => {16805 // * real-time (`.real`) sleeps with absolute deadlines
16790 return std.math.minInt(windows.LARGE_INTEGER); // infinite timeout16806 // * monotonic (`.awake`/`.boot`) sleeps with relative durations
16791 },16807 switch (deadline.clock) {
16792 .deadline => |deadline| {16808 .cpu_process, .cpu_thread => unreachable, // cannot sleep for CPU time
16793 const nanoseconds = deadline.raw.nanoseconds;16809 .real => {
16794 return @intCast(@divTrunc(nanoseconds, 100));16810 return @intCast(@max(@divTrunc(deadline.raw.nanoseconds, 100), 0));
16795 },16811 },
16796 .duration => |duration| {16812 .awake, .boot => {
16797 const now_timestamp = nowWindows(duration.clock) catch unreachable;16813 const duration = try deadline.durationFromNow(ioBasic(t));
16798 const deadline_ns = now_timestamp.nanoseconds + duration.raw.nanoseconds;16814 return @intCast(@min(@divTrunc(-duration.raw.nanoseconds, 100), -1));
16799 return @intCast(@divTrunc(deadline_ns, 100));
16800 },16815 },
16801 }16816 }
16802}16817}