| ... | @@ -1314,6 +1314,13 @@ const AlertableSyscall = struct { | ... | @@ -1314,6 +1314,13 @@ const AlertableSyscall = struct { |
| 1314 | } | 1314 | } |
| 1315 | }; | 1315 | }; |
| 1316 | | 1316 | |
| | 1317 | fn noopApc(_: ?*anyopaque, _: *windows.IO_STATUS_BLOCK, _: windows.ULONG) callconv(.winapi) void {} |
| | 1318 | |
| | 1319 | fn waitForApcOrAlert() void { |
| | 1320 | const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER); |
| | 1321 | _ = windows.ntdll.NtDelayExecution(windows.TRUE, &infinite_timeout); |
| | 1322 | } |
| | 1323 | |
| 1317 | const max_iovecs_len = 8; | 1324 | const max_iovecs_len = 8; |
| 1318 | const splat_buffer_size = 64; | 1325 | const splat_buffer_size = 64; |
| 1319 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; | 1326 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; |
| ... | @@ -8371,40 +8378,41 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us | ... | @@ -8371,40 +8378,41 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8371 | const buffer = data[index]; | 8378 | const buffer = data[index]; |
| 8372 | | 8379 | |
| 8373 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; | 8380 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| 8374 | var done: bool = false; | 8381 | const syscall: Syscall = try .start(); |
| 8375 | const max_delay_interval: windows.LARGE_INTEGER = std.math.minInt(i64); | 8382 | while (true) { |
| 8376 | | 8383 | io_status_block.u.Status = .PENDING; |
| 8377 | read: { | 8384 | switch (windows.ntdll.NtReadFile( |
| 8378 | const syscall: Syscall = try .start(); | 8385 | file.handle, |
| 8379 | while (true) { | 8386 | null, // event |
| 8380 | switch (windows.ntdll.NtReadFile( | 8387 | noopApc, // apc callback |
| 8381 | file.handle, | 8388 | null, // apc context |
| 8382 | null, // event | 8389 | &io_status_block, |
| 8383 | flagApc, // apc callback | 8390 | buffer.ptr, |
| 8384 | &done, // apc context | 8391 | @min(std.math.maxInt(u32), buffer.len), |
| 8385 | &io_status_block, | 8392 | null, // byte offset |
| 8386 | buffer.ptr, | 8393 | null, // key |
| 8387 | @min(std.math.maxInt(u32), buffer.len), | 8394 | )) { |
| 8388 | null, // byte offset | 8395 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => { |
| 8389 | null, // key | 8396 | syscall.finish(); |
| 8390 | )) { | 8397 | return io_status_block.Information; |
| 8391 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => break :read syscall.finish(), | 8398 | }, |
| 8392 | .PENDING => break, | 8399 | .PENDING => break, |
| 8393 | .CANCELLED => { | 8400 | .CANCELLED => { |
| 8394 | try syscall.checkCancel(); | 8401 | try syscall.checkCancel(); |
| 8395 | continue; | 8402 | continue; |
| 8396 | }, | 8403 | }, |
| 8397 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), | 8404 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8398 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), | 8405 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8399 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), | 8406 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 8400 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file | 8407 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file |
| 8401 | else => |status| return syscall.unexpectedNtstatus(status), | 8408 | else => |status| return syscall.unexpectedNtstatus(status), |
| 8402 | } | | |
| 8403 | } | 8409 | } |
| | 8410 | } |
| | 8411 | { |
| 8404 | // Once we get here we received PENDING so we must not return from the | 8412 | // Once we get here we received PENDING so we must not return from the |
| 8405 | // function until the operation completes. | 8413 | // function until the operation completes. |
| 8406 | defer while (!done) { | 8414 | defer while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8407 | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); | 8415 | waitForApcOrAlert(); |
| 8408 | }; | 8416 | }; |
| 8409 | | 8417 | |
| 8410 | const alertable_syscall = syscall.toAlertable() catch |err| switch (err) { | 8418 | const alertable_syscall = syscall.toAlertable() catch |err| switch (err) { |
| ... | @@ -8414,36 +8422,25 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us | ... | @@ -8414,36 +8422,25 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8414 | }, | 8422 | }, |
| 8415 | }; | 8423 | }; |
| 8416 | defer alertable_syscall.finish(); | 8424 | defer alertable_syscall.finish(); |
| 8417 | while (!done) { | 8425 | waitForApcOrAlert(); |
| 8418 | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); | 8426 | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8419 | alertable_syscall.checkCancel() catch |err| switch (err) { | 8427 | alertable_syscall.checkCancel() catch |err| switch (err) { |
| 8420 | error.Canceled => |e| { | 8428 | error.Canceled => |e| { |
| 8421 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); | 8429 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8422 | return e; | 8430 | return e; |
| 8423 | }, | 8431 | }, |
| 8424 | }; | 8432 | }; |
| | 8433 | waitForApcOrAlert(); |
| 8425 | } | 8434 | } |
| 8426 | } | 8435 | } |
| 8427 | | | |
| 8428 | switch (io_status_block.u.Status) { | 8436 | switch (io_status_block.u.Status) { |
| 8429 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => {}, | 8437 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => return io_status_block.Information, |
| | 8438 | .PENDING => unreachable, // cannot return until the operation completes |
| 8430 | .INVALID_DEVICE_REQUEST => return error.IsDir, | 8439 | .INVALID_DEVICE_REQUEST => return error.IsDir, |
| 8431 | .LOCK_NOT_GRANTED => return error.LockViolation, | 8440 | .LOCK_NOT_GRANTED => return error.LockViolation, |
| 8432 | .ACCESS_DENIED => return error.AccessDenied, | 8441 | .ACCESS_DENIED => return error.AccessDenied, |
| 8433 | else => |status| return windows.unexpectedStatus(status), | 8442 | else => |status| return windows.unexpectedStatus(status), |
| 8434 | } | 8443 | } |
| 8435 | return io_status_block.Information; | | |
| 8436 | } | | |
| 8437 | | | |
| 8438 | fn flagApc( | | |
| 8439 | apc_context: ?*anyopaque, | | |
| 8440 | io_status_block: *windows.IO_STATUS_BLOCK, | | |
| 8441 | unused: windows.ULONG, | | |
| 8442 | ) callconv(.winapi) void { | | |
| 8443 | const flag: *bool = @ptrCast(apc_context); | | |
| 8444 | flag.* = true; | | |
| 8445 | _ = io_status_block; | | |
| 8446 | _ = unused; | | |
| 8447 | } | 8444 | } |
| 8448 | | 8445 | |
| 8449 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { | 8446 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |
| ... | @@ -14646,7 +14643,7 @@ fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { | ... | @@ -14646,7 +14643,7 @@ fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { |
| 14646 | t.mutex.lock(); // Another thread might have won the race. | 14643 | t.mutex.lock(); // Another thread might have won the race. |
| 14647 | defer t.mutex.unlock(); | 14644 | defer t.mutex.unlock(); |
| 14648 | if (t.random_file.handle) |prev_handle| { | 14645 | if (t.random_file.handle) |prev_handle| { |
| 14649 | _ = windows.ntdll.NtClose(fresh_handle); | 14646 | windows.CloseHandle(fresh_handle); |
| 14650 | return prev_handle; | 14647 | return prev_handle; |
| 14651 | } else { | 14648 | } else { |
| 14652 | t.random_file.handle = fresh_handle; | 14649 | t.random_file.handle = fresh_handle; |