authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-28 21:02:43-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 12:10:02-08:00
log816f70d0c3ba55d0b9cffcc7474ad595c1676d43
tree9847262e51b8e0af97942700b22216c01841feeb
parent0ac63ff9dffa7311cc539b52e037bd38d2019683

std.Io.Threaded: compress ntReadFile logic

Just use the ntstatus field rather than an additional enum

1 files changed, 61 insertions(+), 76 deletions(-)

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