std.Io: minor cleanups to futex and event

mainly avoid an unnecessary `@ptrCast`
This commit is contained in:
Andrew Kelley 2025-12-22 21:46:08 -08:00
parent 6ece10f63d
commit bd6acbf7da
2 changed files with 19 additions and 20 deletions

View file

@ -1314,17 +1314,21 @@ pub fn futexWait(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, e
/// wakeups are possible. It remains the caller's responsibility to differentiate between these
/// three possible wake-up reasons if necessary.
pub fn futexWaitTimeout(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T, timeout: Timeout) Cancelable!void {
comptime assert(@sizeOf(T) == 4);
const expected_raw: *align(1) const u32 = @ptrCast(&expected);
return io.vtable.futexWait(io.userdata, @ptrCast(ptr), expected_raw.*, timeout);
const expected_int: u32 = switch (@typeInfo(T)) {
.@"enum" => @bitCast(@intFromEnum(expected)),
else => @bitCast(expected),
};
return io.vtable.futexWait(io.userdata, @ptrCast(ptr), expected_int, timeout);
}
/// Same as `futexWait`, except does not introduce a cancelation point.
///
/// For a description of cancelation and cancelation points, see `Future.cancel`.
pub fn futexWaitUncancelable(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T) void {
comptime assert(@sizeOf(T) == @sizeOf(u32));
const expected_raw: *align(1) const u32 = @ptrCast(&expected);
io.vtable.futexWaitUncancelable(io.userdata, @ptrCast(ptr), expected_raw.*);
const expected_int: u32 = switch (@typeInfo(T)) {
.@"enum" => @bitCast(@intFromEnum(expected)),
else => @bitCast(expected),
};
io.vtable.futexWaitUncancelable(io.userdata, @ptrCast(ptr), expected_int);
}
/// Unblocks pending futex waits on `ptr`, up to a limit of `max_waiters` calls.
pub fn futexWake(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, max_waiters: u32) void {
@ -1576,10 +1580,12 @@ pub const Event = enum(u32) {
}
}
pub const WaitTimeoutError = error{Timeout} || Cancelable;
/// Blocks the calling thread until either the logical boolean is set, the timeout expires, or a
/// spurious wakeup occurs. If the timeout expires or a spurious wakeup occurs, `error.Timeout`
/// is returned.
pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) (error{Timeout} || Cancelable)!void {
pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {
if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {
.unset => unreachable,
.waiting => assert(!builtin.single_threaded), // invalid state

View file

@ -292,7 +292,7 @@ const Thread = struct {
.INTR => {}, // caller's responsibility to retry
.AGAIN => {}, // ptr.* != expect
.INVAL => {}, // possibly timeout overflow
.TIMEDOUT => {}, // timeout
.TIMEDOUT => {},
.FAULT => recoverableOsBugDetected(), // ptr was invalid
else => recoverableOsBugDetected(),
}
@ -1548,6 +1548,7 @@ fn cancel(
}
fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io.Timeout) Io.Cancelable!void {
if (builtin.single_threaded) unreachable; // Deadlock.
const t: *Threaded = @ptrCast(@alignCast(userdata));
const current_thread = Thread.getCurrent(t);
const t_io = ioBasic(t);
@ -1555,29 +1556,21 @@ fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io.
const d = (timeout.toDurationFromNow(t_io) catch break :ns 10) orelse break :ns null;
break :ns std.math.lossyCast(u64, d.raw.toNanoseconds());
};
switch (native_os) {
.illumos, .netbsd, .openbsd => @panic("TODO"),
else => try current_thread.futexWaitTimed(ptr, expected, timeout_ns),
}
return Thread.futexWaitTimed(current_thread, ptr, expected, timeout_ns);
}
fn futexWaitUncancelable(userdata: ?*anyopaque, ptr: *const u32, expected: u32) void {
if (builtin.single_threaded) unreachable; // Deadlock.
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
switch (native_os) {
.illumos, .netbsd, .openbsd => @panic("TODO"),
else => Thread.futexWaitUncancelable(ptr, expected),
}
Thread.futexWaitUncancelable(ptr, expected);
}
fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void {
if (builtin.single_threaded) unreachable; // Nothing to wake up.
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
switch (native_os) {
.illumos, .netbsd, .openbsd => @panic("TODO"),
else => Thread.futexWake(ptr, max_waiters),
}
Thread.futexWake(ptr, max_waiters);
}
const dirCreateDir = switch (native_os) {