feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.Syscall
const Syscall = struct
File
Code
const Syscall = struct {
thread: ?*Thread,
fn start() Io.Cancelable!Syscall {
const thread = Thread.current orelse return .{ .thread = null };
switch (thread.cancel_protection) {
.blocked => return .{ .thread = null },
.unblocked => {},
}
switch (thread.status.fetchOr(.{
.cancelation = @fromBackingInt(@intCast(0b011)),
.awaitable = .null,
}, .monotonic).cancelation) {
.parked => unreachable,
.blocked => unreachable,
.blocked_alertable => unreachable,
.blocked_alertable_canceling => unreachable,
.blocked_canceling => unreachable,
.none => return .{ .thread = thread },
.canceling => return error.Canceled,
.canceled => return .{ .thread = null },
}
}
fn checkCancel(s: Syscall) Io.Cancelable!void {
const thread = s.thread orelse return;
switch (thread.status.fetchOr(.{
.cancelation = @fromBackingInt(@intCast(0b010)),
.awaitable = .null,
}, .monotonic).cancelation) {
.none => unreachable,
.parked => unreachable,
.blocked_alertable => unreachable,
.blocked_alertable_canceling => unreachable,
.canceling => unreachable,
.canceled => unreachable,
.blocked => {},
.blocked_canceling => return error.Canceled,
}
}
fn finish(s: Syscall) void {
const thread = s.thread orelse return;
switch (thread.status.fetchXor(.{
.cancelation = @fromBackingInt(@intCast(0b011)),
.awaitable = .null,
}, .monotonic).cancelation) {
.none => unreachable,
.parked => unreachable,
.blocked_alertable => unreachable,
.blocked_alertable_canceling => unreachable,
.canceling => unreachable,
.canceled => unreachable,
.blocked => {},
.blocked_canceling => {},
}
}
fn toAlertable(s: Syscall) Io.Cancelable!AlertableSyscall {
comptime assert(is_windows);
const thread = s.thread orelse return .{ .thread = null };
var prev = thread.status.load(.monotonic);
while (true) prev = switch (prev.cancelation) {
.none => unreachable,
.parked => unreachable,
.blocked_alertable => unreachable,
.blocked_alertable_canceling => unreachable,
.canceling => unreachable,
.canceled => unreachable,
.blocked => thread.status.cmpxchgWeak(prev, .{
.cancelation = .blocked_alertable,
.awaitable = prev.awaitable,
}, .monotonic, .monotonic) orelse return .{ .thread = thread },
.blocked_canceling => thread.status.cmpxchgWeak(prev, .{
.cancelation = .canceled,
.awaitable = prev.awaitable,
}, .monotonic, .monotonic) orelse return error.Canceled,
};
}
fn fail(s: Syscall, err: anytype) @TypeOf(err) {
s.finish();
return err;
}
fn errnoBug(s: Syscall, err: posix.E) Io.UnexpectedError {
@branchHint(.cold);
s.finish();
return Threaded.errnoBug(err);
}
fn unexpectedErrno(s: Syscall, err: posix.E) Io.UnexpectedError {
@branchHint(.cold);
s.finish();
return posix.unexpectedErrno(err);
}
fn ntstatusBug(s: Syscall, status: windows.NTSTATUS) Io.UnexpectedError {
@branchHint(.cold);
s.finish();
return windows.statusBug(status);
}
fn unexpectedNtstatus(s: Syscall, status: windows.NTSTATUS) Io.UnexpectedError {
@branchHint(.cold);
s.finish();
return windows.unexpectedStatus(status);
}
}