| ... | @@ -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"; |
| ... | @@ -8228,40 +8235,41 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us | ... | @@ -8228,40 +8235,41 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8228 | const buffer = data[index]; | 8235 | const buffer = data[index]; |
| 8229 | | 8236 | |
| 8230 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; | 8237 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| 8231 | var done: bool = false; | 8238 | const syscall: Syscall = try .start(); |
| 8232 | const max_delay_interval: windows.LARGE_INTEGER = std.math.minInt(i64); | 8239 | while (true) { |
| 8233 | | 8240 | io_status_block.u.Status = .PENDING; |
| 8234 | read: { | 8241 | switch (windows.ntdll.NtReadFile( |
| 8235 | const syscall: Syscall = try .start(); | 8242 | file.handle, |
| 8236 | while (true) { | 8243 | null, // event |
| 8237 | switch (windows.ntdll.NtReadFile( | 8244 | noopApc, // apc callback |
| 8238 | file.handle, | 8245 | null, // apc context |
| 8239 | null, // event | 8246 | &io_status_block, |
| 8240 | flagApc, // apc callback | 8247 | buffer.ptr, |
| 8241 | &done, // apc context | 8248 | @min(std.math.maxInt(u32), buffer.len), |
| 8242 | &io_status_block, | 8249 | null, // byte offset |
| 8243 | buffer.ptr, | 8250 | null, // key |
| 8244 | @min(std.math.maxInt(u32), buffer.len), | 8251 | )) { |
| 8245 | null, // byte offset | 8252 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => { |
| 8246 | null, // key | 8253 | syscall.finish(); |
| 8247 | )) { | 8254 | return io_status_block.Information; |
| 8248 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => break :read syscall.finish(), | 8255 | }, |
| 8249 | .PENDING => break, | 8256 | .PENDING => break, |
| 8250 | .CANCELLED => { | 8257 | .CANCELLED => { |
| 8251 | try syscall.checkCancel(); | 8258 | try syscall.checkCancel(); |
| 8252 | continue; | 8259 | continue; |
| 8253 | }, | 8260 | }, |
| 8254 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), | 8261 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8255 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), | 8262 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8256 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), | 8263 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 8257 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file | 8264 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file |
| 8258 | else => |status| return syscall.unexpectedNtstatus(status), | 8265 | else => |status| return syscall.unexpectedNtstatus(status), |
| 8259 | } | | |
| 8260 | } | 8266 | } |
| | 8267 | } |
| | 8268 | { |
| 8261 | // Once we get here we received PENDING so we must not return from the | 8269 | // Once we get here we received PENDING so we must not return from the |
| 8262 | // function until the operation completes. | 8270 | // function until the operation completes. |
| 8263 | defer while (!done) { | 8271 | defer while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8264 | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); | 8272 | waitForApcOrAlert(); |
| 8265 | }; | 8273 | }; |
| 8266 | | 8274 | |
| 8267 | const alertable_syscall = syscall.toAlertable() catch |err| switch (err) { | 8275 | const alertable_syscall = syscall.toAlertable() catch |err| switch (err) { |
| ... | @@ -8271,36 +8279,25 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us | ... | @@ -8271,36 +8279,25 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8271 | }, | 8279 | }, |
| 8272 | }; | 8280 | }; |
| 8273 | defer alertable_syscall.finish(); | 8281 | defer alertable_syscall.finish(); |
| 8274 | while (!done) { | 8282 | waitForApcOrAlert(); |
| 8275 | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); | 8283 | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8276 | alertable_syscall.checkCancel() catch |err| switch (err) { | 8284 | alertable_syscall.checkCancel() catch |err| switch (err) { |
| 8277 | error.Canceled => |e| { | 8285 | error.Canceled => |e| { |
| 8278 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); | 8286 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8279 | return e; | 8287 | return e; |
| 8280 | }, | 8288 | }, |
| 8281 | }; | 8289 | }; |
| | 8290 | waitForApcOrAlert(); |
| 8282 | } | 8291 | } |
| 8283 | } | 8292 | } |
| 8284 | | | |
| 8285 | switch (io_status_block.u.Status) { | 8293 | switch (io_status_block.u.Status) { |
| 8286 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => {}, | 8294 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => return io_status_block.Information, |
| | 8295 | .PENDING => unreachable, // cannot return until the operation completes |
| 8287 | .INVALID_DEVICE_REQUEST => return error.IsDir, | 8296 | .INVALID_DEVICE_REQUEST => return error.IsDir, |
| 8288 | .LOCK_NOT_GRANTED => return error.LockViolation, | 8297 | .LOCK_NOT_GRANTED => return error.LockViolation, |
| 8289 | .ACCESS_DENIED => return error.AccessDenied, | 8298 | .ACCESS_DENIED => return error.AccessDenied, |
| 8290 | else => |status| return windows.unexpectedStatus(status), | 8299 | else => |status| return windows.unexpectedStatus(status), |
| 8291 | } | 8300 | } |
| 8292 | return io_status_block.Information; | | |
| 8293 | } | | |
| 8294 | | | |
| 8295 | fn flagApc( | | |
| 8296 | apc_context: ?*anyopaque, | | |
| 8297 | io_status_block: *windows.IO_STATUS_BLOCK, | | |
| 8298 | unused: windows.ULONG, | | |
| 8299 | ) callconv(.winapi) void { | | |
| 8300 | const flag: *bool = @ptrCast(apc_context); | | |
| 8301 | flag.* = true; | | |
| 8302 | _ = io_status_block; | | |
| 8303 | _ = unused; | | |
| 8304 | } | 8301 | } |
| 8305 | | 8302 | |
| 8306 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { | 8303 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |
| ... | @@ -14407,7 +14404,7 @@ fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { | ... | @@ -14407,7 +14404,7 @@ fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { |
| 14407 | t.mutex.lock(); // Another thread might have won the race. | 14404 | t.mutex.lock(); // Another thread might have won the race. |
| 14408 | defer t.mutex.unlock(); | 14405 | defer t.mutex.unlock(); |
| 14409 | if (t.random_file.handle) |prev_handle| { | 14406 | if (t.random_file.handle) |prev_handle| { |
| 14410 | _ = windows.ntdll.NtClose(fresh_handle); | 14407 | windows.CloseHandle(fresh_handle); |
| 14411 | return prev_handle; | 14408 | return prev_handle; |
| 14412 | } else { | 14409 | } else { |
| 14413 | t.random_file.handle = fresh_handle; | 14410 | t.random_file.handle = fresh_handle; |