| ... | ... | @@ -2719,7 +2719,13 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2719 | 2719 | } |
| 2720 | 2720 | } |
| 2721 | 2721 | |
| 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 | }; |
| 2723 | 2729 | |
| 2724 | 2730 | while (true) { |
| 2725 | 2731 | var any_pending = false; |
| ... | ... | @@ -2741,6 +2747,16 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2741 | 2747 | } |
| 2742 | 2748 | if (b.user.complete_head != complete_tail) return; |
| 2743 | 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 | 2760 | const alertable_syscall = try AlertableSyscall.start(); |
| 2745 | 2761 | const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval); |
| 2746 | 2762 | alertable_syscall.finish(); |
| ... | ... | @@ -16784,19 +16800,18 @@ fn park(opt_deadline: ?Io.Clock.Timestamp, addr_hint: ?*const anyopaque) error{T |
| 16784 | 16800 | } |
| 16785 | 16801 | } |
| 16786 | 16802 | |
| 16787 | | fn 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)); |
| 16803 | fn 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)); |
| 16795 | 16811 | }, |
| 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)); |
| 16800 | 16815 | }, |
| 16801 | 16816 | } |
| 16802 | 16817 | } |