mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 04:24:33 +01:00
std.Io.Threaded: implement APC cancelation
specifically the call to NtCancelIoFileEx
This commit is contained in:
parent
1e3072ec46
commit
e705ad8302
2 changed files with 29 additions and 10 deletions
|
|
@ -632,12 +632,17 @@ const Thread = struct {
|
|||
cancel_protection: Io.CancelProtection,
|
||||
/// Always released when `Status.cancelation` is set to `.parked`.
|
||||
futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,
|
||||
apc_context: if (is_windows) ?*anyopaque else void,
|
||||
apc: Apc,
|
||||
/// Used only by group cancelation code for temporary storage.
|
||||
interrupt_method: InterruptMethod,
|
||||
|
||||
csprng: Csprng,
|
||||
|
||||
const Apc = if (is_windows) struct {
|
||||
handle: windows.HANDLE,
|
||||
iosb: ?*windows.IO_STATUS_BLOCK,
|
||||
} else void;
|
||||
|
||||
const Handle = Handle: {
|
||||
if (std.Thread.use_pthreads) break :Handle std.c.pthread_t;
|
||||
if (is_windows) break :Handle windows.HANDLE;
|
||||
|
|
@ -1116,7 +1121,14 @@ const Thread = struct {
|
|||
};
|
||||
},
|
||||
.dns => @panic("TODO call GetAddrInfoExCancel"),
|
||||
.apc => @panic("TODO call NtCancelIoFileEx"),
|
||||
.apc => {
|
||||
var iosb: windows.IO_STATUS_BLOCK = undefined;
|
||||
return switch (windows.ntdll.NtCancelIoFileEx(thread.apc.handle, thread.apc.iosb, &iosb)) {
|
||||
.NOT_FOUND => true, // this might mean the operation hasn't started yet
|
||||
.SUCCESS => false, // the OS confirmed that our cancelation worked
|
||||
else => false,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
else => {
|
||||
|
|
@ -1213,9 +1225,9 @@ const Syscall = struct {
|
|||
/// `NtCancelIoFileEx` to interrupt the wait.
|
||||
///
|
||||
/// Windows only, called from blocked state only.
|
||||
fn toApc(s: Syscall, apc_context: ?*anyopaque) Io.Cancelable!void {
|
||||
fn toApc(s: Syscall, apc: Thread.Apc) Io.Cancelable!void {
|
||||
const thread = s.thread orelse return;
|
||||
thread.apc_context = apc_context;
|
||||
thread.apc = apc;
|
||||
var prev = thread.status.load(.monotonic);
|
||||
while (true) prev = switch (prev.cancelation) {
|
||||
.none => unreachable,
|
||||
|
|
@ -1554,7 +1566,7 @@ fn worker(t: *Threaded) void {
|
|||
.cancel_protection = .unblocked,
|
||||
.futex_waiter = undefined,
|
||||
.csprng = .{},
|
||||
.apc_context = undefined,
|
||||
.apc = undefined,
|
||||
.interrupt_method = undefined,
|
||||
};
|
||||
Thread.current = &thread;
|
||||
|
|
@ -8458,10 +8470,17 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us
|
|||
//else => |status| return syscall.unexpectedNtstatus(status),
|
||||
}
|
||||
}
|
||||
try syscall.toApc(&done);
|
||||
try syscall.toApc(.{ .handle = file.handle, .iosb = &io_status_block });
|
||||
while (true) {
|
||||
switch (windows.ntdll.NtDelayExecution(1, null)) {
|
||||
.USER_APC => break syscall.finishApc(),
|
||||
.USER_APC => {
|
||||
if (!done) {
|
||||
// Other APC work was queued before calling into this function.
|
||||
try syscall.checkCancelApc();
|
||||
continue;
|
||||
}
|
||||
break syscall.finishApc();
|
||||
},
|
||||
.SUCCESS, .CANCELLED => {
|
||||
try syscall.checkCancelApc();
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -601,11 +601,11 @@ pub extern "ntdll" fn NtDelayExecution(
|
|||
|
||||
pub extern "ntdll" fn NtCancelIoFileEx(
|
||||
FileHandle: HANDLE,
|
||||
IoRequestToCancel: *const IO_STATUS_BLOCK,
|
||||
IoRequestToCancel: ?*IO_STATUS_BLOCK,
|
||||
IoStatusBlock: *IO_STATUS_BLOCK,
|
||||
) callconv(.winapi) NTSTATUS;
|
||||
|
||||
pub extern "ntdll" fn NtCancelIoFile(
|
||||
handle: HANDLE,
|
||||
iosbToCancel: *const IO_STATUS_BLOCK,
|
||||
FileHandle: HANDLE,
|
||||
IoRequestToCancel: ?*IO_STATUS_BLOCK,
|
||||
) callconv(.winapi) NTSTATUS;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue