| ... | ... | @@ -2695,7 +2695,10 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2695 | 2695 | const op = ring[submit_head.index(len)]; |
| 2696 | 2696 | const operation = &operations[op]; |
| 2697 | 2697 | const metadata = &metadatas[op]; |
| 2698 | | metadata.* = .{ .iosb = undefined, .pending = false }; |
| 2698 | metadata.* = .{ .iosb = .{ |
| 2699 | .u = .{ .Status = .PENDING }, |
| 2700 | .Information = 0, |
| 2701 | }, .pending = false }; |
| 2699 | 2702 | switch (operation.*) { |
| 2700 | 2703 | .noop => |*o| { |
| 2701 | 2704 | _ = o.status.unstarted; |
| ... | ... | @@ -2704,15 +2707,13 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa |
| 2704 | 2707 | }, |
| 2705 | 2708 | .file_read_streaming => |*o| { |
| 2706 | 2709 | _ = o.status.unstarted; |
| 2707 | | switch (try ntReadFile(o.file.handle, o.data, &metadata.iosb)) { |
| 2708 | | .status => { |
| 2709 | | o.status = .{ .result = ntReadFileResult(&metadata.iosb) }; |
| 2710 | | submitComplete(ring, &complete_tail, op); |
| 2711 | | }, |
| 2712 | | .pending => { |
| 2713 | | o.status = .{ .pending = b }; |
| 2714 | | metadata.pending = true; |
| 2715 | | }, |
| 2710 | try ntReadFile(o.file.handle, o.data, &metadata.iosb); |
| 2711 | if (@atomicLoad(windows.NTSTATUS, &metadata.iosb.u.Status, .acquire) == .PENDING) { |
| 2712 | o.status = .{ .pending = b }; |
| 2713 | metadata.pending = true; |
| 2714 | } else { |
| 2715 | o.status = .{ .result = ntReadFileResult(&metadata.iosb) }; |
| 2716 | submitComplete(ring, &complete_tail, op); |
| 2716 | 2717 | } |
| 2717 | 2718 | }, |
| 2718 | 2719 | } |
| ... | ... | @@ -8680,44 +8681,36 @@ fn fileReadStreamingPosix(file: File, data: []const []u8) File.ReadStreamingErro |
| 8680 | 8681 | } |
| 8681 | 8682 | |
| 8682 | 8683 | fn fileReadStreamingWindows(file: File, data: []const []u8) File.ReadStreamingError!usize { |
| 8683 | | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| 8684 | | if (ntReadFile(file.handle, data, &io_status_block)) |result| switch (result) { |
| 8685 | | .status => return ntReadFileResult(&io_status_block), |
| 8686 | | .pending => { |
| 8687 | | // Once we get here we received PENDING so we must not return from the |
| 8688 | | // function until the operation completes. |
| 8689 | | defer while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8690 | | waitForApcOrAlert(); |
| 8691 | | }; |
| 8692 | | |
| 8693 | | const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) { |
| 8694 | | error.Canceled => |e| { |
| 8695 | | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8696 | | return e; |
| 8697 | | }, |
| 8698 | | }; |
| 8699 | | waitForApcOrAlert(); |
| 8700 | | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8701 | | alertable_syscall.checkCancel() catch |err| switch (err) { |
| 8702 | | error.Canceled => |e| { |
| 8703 | | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8704 | | return e; |
| 8705 | | }, |
| 8706 | | }; |
| 8707 | | waitForApcOrAlert(); |
| 8708 | | } |
| 8709 | | alertable_syscall.finish(); |
| 8710 | | }, |
| 8711 | | } else |err| return err; |
| 8684 | var io_status_block: windows.IO_STATUS_BLOCK = .{ |
| 8685 | .u = .{ .Status = .PENDING }, |
| 8686 | .Information = 0, |
| 8687 | }; |
| 8688 | try ntReadFile(file.handle, data, &io_status_block); |
| 8689 | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8690 | // Once we get here we must not return from the function until the |
| 8691 | // operation completes, thereby releasing reference to io_status_block. |
| 8692 | const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) { |
| 8693 | error.Canceled => |e| { |
| 8694 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8695 | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8696 | waitForApcOrAlert(); |
| 8697 | } |
| 8698 | return e; |
| 8699 | }, |
| 8700 | }; |
| 8701 | waitForApcOrAlert(); |
| 8702 | alertable_syscall.finish(); |
| 8703 | } |
| 8712 | 8704 | return ntReadFileResult(&io_status_block); |
| 8713 | 8705 | } |
| 8714 | 8706 | |
| 8715 | | fn ntReadFileResult(io_status_block: *windows.IO_STATUS_BLOCK) !usize { |
| 8707 | fn ntReadFileResult(io_status_block: *const windows.IO_STATUS_BLOCK) !usize { |
| 8716 | 8708 | switch (io_status_block.u.Status) { |
| 8709 | .PENDING => unreachable, |
| 8710 | .CANCELLED => unreachable, |
| 8717 | 8711 | .SUCCESS => return io_status_block.Information, |
| 8718 | 8712 | .END_OF_FILE => return error.EndOfStream, |
| 8719 | 8713 | .PIPE_BROKEN => return error.EndOfStream, |
| 8720 | | .PENDING => unreachable, |
| 8721 | 8714 | .INVALID_DEVICE_REQUEST => return error.IsDir, |
| 8722 | 8715 | .LOCK_NOT_GRANTED => return error.LockViolation, |
| 8723 | 8716 | .ACCESS_DENIED => return error.AccessDenied, |
| ... | ... | @@ -8725,50 +8718,42 @@ fn ntReadFileResult(io_status_block: *windows.IO_STATUS_BLOCK) !usize { |
| 8725 | 8718 | } |
| 8726 | 8719 | } |
| 8727 | 8720 | |
| 8728 | | fn ntReadFile(handle: windows.HANDLE, data: []const []u8, iosb: *windows.IO_STATUS_BLOCK) Io.Cancelable!enum { status, pending } { |
| 8721 | fn ntReadFile(handle: windows.HANDLE, data: []const []u8, iosb: *windows.IO_STATUS_BLOCK) Io.Cancelable!void { |
| 8729 | 8722 | var index: usize = 0; |
| 8730 | 8723 | while (index < data.len and data[index].len == 0) index += 1; |
| 8731 | 8724 | if (index == data.len) { |
| 8732 | 8725 | iosb.u.Status = .SUCCESS; |
| 8733 | 8726 | iosb.Information = 0; |
| 8734 | | return .status; |
| 8727 | return; |
| 8735 | 8728 | } |
| 8736 | 8729 | const buffer = data[index]; |
| 8737 | 8730 | |
| 8738 | 8731 | const syscall: Syscall = try .start(); |
| 8739 | | while (true) { |
| 8740 | | iosb.u.Status = .PENDING; |
| 8741 | | switch (windows.ntdll.NtReadFile( |
| 8742 | | handle, |
| 8743 | | null, // event |
| 8744 | | noopApc, // apc callback |
| 8745 | | null, // apc context |
| 8746 | | iosb, |
| 8747 | | buffer.ptr, |
| 8748 | | @min(std.math.maxInt(u32), buffer.len), |
| 8749 | | null, // byte offset |
| 8750 | | null, // key |
| 8751 | | )) { |
| 8752 | | .PENDING => { |
| 8753 | | syscall.finish(); |
| 8754 | | return .pending; |
| 8755 | | }, |
| 8756 | | .SUCCESS => { |
| 8757 | | syscall.finish(); |
| 8758 | | iosb.u.Status = .SUCCESS; |
| 8759 | | return .status; |
| 8760 | | }, |
| 8761 | | .CANCELLED => { |
| 8762 | | try syscall.checkCancel(); |
| 8763 | | continue; |
| 8764 | | }, |
| 8765 | | else => |status| { |
| 8766 | | syscall.finish(); |
| 8767 | | iosb.u.Status = status; |
| 8768 | | return .status; |
| 8769 | | }, |
| 8770 | | } |
| 8771 | | } |
| 8732 | while (true) switch (windows.ntdll.NtReadFile( |
| 8733 | handle, |
| 8734 | null, // event |
| 8735 | noopApc, // apc callback |
| 8736 | null, // apc context |
| 8737 | iosb, |
| 8738 | buffer.ptr, |
| 8739 | @min(std.math.maxInt(u32), buffer.len), |
| 8740 | null, // byte offset |
| 8741 | null, // key |
| 8742 | )) { |
| 8743 | .PENDING => { |
| 8744 | syscall.finish(); |
| 8745 | return; |
| 8746 | }, |
| 8747 | .CANCELLED => { |
| 8748 | try syscall.checkCancel(); |
| 8749 | continue; |
| 8750 | }, |
| 8751 | else => |status| { |
| 8752 | syscall.finish(); |
| 8753 | iosb.u.Status = status; |
| 8754 | return; |
| 8755 | }, |
| 8756 | }; |
| 8772 | 8757 | } |
| 8773 | 8758 | |
| 8774 | 8759 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |