| ... | ... | @@ -2560,17 +2560,31 @@ fn batchWait(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout) Io.Batch. |
| 2560 | 2560 | const deadline = timeout.toDeadline(t_io) catch return error.UnsupportedClock; |
| 2561 | 2561 | const max_poll_ms = std.math.maxInt(i32); |
| 2562 | 2562 | while (true) { |
| 2563 | | const timeout_ms: i32 = if (deadline) |d| t: { |
| 2563 | const timeout_ms: i32 = t: { |
| 2564 | if (b.user.complete_head != complete_tail) { |
| 2565 | // It is legal to call batchWait with already completed |
| 2566 | // operations in the ring. In such case, we need to avoid |
| 2567 | // blocking in the poll syscall, but we can still take this |
| 2568 | // opportunity to find additional ready operations. |
| 2569 | break :t 0; |
| 2570 | } |
| 2571 | const d = deadline orelse break :t -1; |
| 2564 | 2572 | const duration = d.durationFromNow(t_io) catch return error.UnsupportedClock; |
| 2565 | 2573 | if (duration.raw.nanoseconds <= 0) return error.Timeout; |
| 2566 | 2574 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); |
| 2567 | | } else -1; |
| 2575 | }; |
| 2568 | 2576 | const syscall = try Syscall.start(); |
| 2569 | 2577 | const rc = posix.system.poll(&poll_buffer, poll_i, timeout_ms); |
| 2570 | 2578 | syscall.finish(); |
| 2571 | 2579 | switch (posix.errno(rc)) { |
| 2572 | 2580 | .SUCCESS => { |
| 2573 | 2581 | if (rc == 0) { |
| 2582 | if (b.user.complete_head != complete_tail) { |
| 2583 | // Since there are already completions available in the |
| 2584 | // queue, this is neither a timeout nor a case for |
| 2585 | // retrying. |
| 2586 | return; |
| 2587 | } |
| 2574 | 2588 | // Although spurious timeouts are OK, when no deadline is |
| 2575 | 2589 | // passed we must not return `error.Timeout`. |
| 2576 | 2590 | if (deadline == null) continue; |
| ... | ... | @@ -2677,8 +2691,6 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2677 | 2691 | b.user.complete_tail = complete_tail; |
| 2678 | 2692 | } |
| 2679 | 2693 | |
| 2680 | | var any_done = false; |
| 2681 | | |
| 2682 | 2694 | while (submit_head != submit_tail) : (submit_head = submit_head.next(len)) { |
| 2683 | 2695 | const op = ring[submit_head.index(len)]; |
| 2684 | 2696 | const operation = &operations[op]; |
| ... | ... | @@ -2688,7 +2700,6 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2688 | 2700 | .noop => |*o| { |
| 2689 | 2701 | _ = o.status.unstarted; |
| 2690 | 2702 | o.status = .{ .result = {} }; |
| 2691 | | any_done = true; |
| 2692 | 2703 | submitComplete(ring, &complete_tail, op); |
| 2693 | 2704 | }, |
| 2694 | 2705 | .file_read_streaming => |*o| { |
| ... | ... | @@ -2696,7 +2707,6 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2696 | 2707 | switch (try ntReadFile(o.file.handle, o.data, &metadata.iosb)) { |
| 2697 | 2708 | .status => { |
| 2698 | 2709 | o.status = .{ .result = ntReadFileResult(&metadata.iosb) }; |
| 2699 | | any_done = true; |
| 2700 | 2710 | submitComplete(ring, &complete_tail, op); |
| 2701 | 2711 | }, |
| 2702 | 2712 | .pending => { |
| ... | ... | @@ -2725,11 +2735,10 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2725 | 2735 | o.status = .{ .result = ntReadFileResult(&metadata.iosb) }; |
| 2726 | 2736 | }, |
| 2727 | 2737 | } |
| 2728 | | any_done = true; |
| 2729 | 2738 | metadata.pending = false; |
| 2730 | 2739 | submitComplete(ring, &complete_tail, op); |
| 2731 | 2740 | } |
| 2732 | | if (any_done) return; |
| 2741 | if (b.user.complete_head != complete_tail) return; |
| 2733 | 2742 | if (!any_pending) return; |
| 2734 | 2743 | const alertable_syscall = try AlertableSyscall.start(); |
| 2735 | 2744 | const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval); |