authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-22 21:46:08-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:12-08:00
logbd6acbf7da55a2497fcfb9c589093612a3fe9680
tree6305654f8efc3c44c4afec344ff09f5fda74113d
parent6ece10f63d91cfa16d8388f8d696368537c1662e

std.Io: minor cleanups to futex and event

mainly avoid an unnecessary `@ptrCast`

2 files changed, 19 insertions(+), 20 deletions(-)

lib/std/Io.zig+13-7
......@@ -1314,17 +1314,21 @@ pub fn futexWait(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, e
13141314/// wakeups are possible. It remains the caller's responsibility to differentiate between these
13151315/// three possible wake-up reasons if necessary.
13161316pub fn futexWaitTimeout(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T, timeout: Timeout) Cancelable!void {
1317 comptime assert(@sizeOf(T) == 4);
1318 const expected_raw: *align(1) const u32 = @ptrCast(&expected);
1319 return io.vtable.futexWait(io.userdata, @ptrCast(ptr), expected_raw.*, timeout);
1317 const expected_int: u32 = switch (@typeInfo(T)) {
1318 .@"enum" => @bitCast(@intFromEnum(expected)),
1319 else => @bitCast(expected),
1320 };
1321 return io.vtable.futexWait(io.userdata, @ptrCast(ptr), expected_int, timeout);
13201322}
13211323/// Same as `futexWait`, except does not introduce a cancelation point.
13221324///
13231325/// For a description of cancelation and cancelation points, see `Future.cancel`.
13241326pub fn futexWaitUncancelable(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T) void {
1325 comptime assert(@sizeOf(T) == @sizeOf(u32));
1326 const expected_raw: *align(1) const u32 = @ptrCast(&expected);
1327 io.vtable.futexWaitUncancelable(io.userdata, @ptrCast(ptr), expected_raw.*);
1327 const expected_int: u32 = switch (@typeInfo(T)) {
1328 .@"enum" => @bitCast(@intFromEnum(expected)),
1329 else => @bitCast(expected),
1330 };
1331 io.vtable.futexWaitUncancelable(io.userdata, @ptrCast(ptr), expected_int);
13281332}
13291333/// Unblocks pending futex waits on `ptr`, up to a limit of `max_waiters` calls.
13301334pub 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) {
15761580 }
15771581 }
15781582
1583 pub const WaitTimeoutError = error{Timeout} || Cancelable;
1584
15791585 /// Blocks the calling thread until either the logical boolean is set, the timeout expires, or a
15801586 /// spurious wakeup occurs. If the timeout expires or a spurious wakeup occurs, `error.Timeout`
15811587 /// is returned.
1582 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) (error{Timeout} || Cancelable)!void {
1588 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {
15831589 if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {
15841590 .unset => unreachable,
15851591 .waiting => assert(!builtin.single_threaded), // invalid state
lib/std/Io/Threaded.zig+6-13
......@@ -292,7 +292,7 @@ const Thread = struct {
292292 .INTR => {}, // caller's responsibility to retry
293293 .AGAIN => {}, // ptr.* != expect
294294 .INVAL => {}, // possibly timeout overflow
295 .TIMEDOUT => {}, // timeout
295 .TIMEDOUT => {},
296296 .FAULT => recoverableOsBugDetected(), // ptr was invalid
297297 else => recoverableOsBugDetected(),
298298 }
......@@ -1548,6 +1548,7 @@ fn cancel(
15481548}
15491549
15501550fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io.Timeout) Io.Cancelable!void {
1551 if (builtin.single_threaded) unreachable; // Deadlock.
15511552 const t: *Threaded = @ptrCast(@alignCast(userdata));
15521553 const current_thread = Thread.getCurrent(t);
15531554 const t_io = ioBasic(t);
......@@ -1555,29 +1556,21 @@ fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io.
15551556 const d = (timeout.toDurationFromNow(t_io) catch break :ns 10) orelse break :ns null;
15561557 break :ns std.math.lossyCast(u64, d.raw.toNanoseconds());
15571558 };
1558 switch (native_os) {
1559 .illumos, .netbsd, .openbsd => @panic("TODO"),
1560 else => try current_thread.futexWaitTimed(ptr, expected, timeout_ns),
1561 }
1559 return Thread.futexWaitTimed(current_thread, ptr, expected, timeout_ns);
15621560}
15631561
15641562fn futexWaitUncancelable(userdata: ?*anyopaque, ptr: *const u32, expected: u32) void {
1563 if (builtin.single_threaded) unreachable; // Deadlock.
15651564 const t: *Threaded = @ptrCast(@alignCast(userdata));
15661565 _ = t;
1567 switch (native_os) {
1568 .illumos, .netbsd, .openbsd => @panic("TODO"),
1569 else => Thread.futexWaitUncancelable(ptr, expected),
1570 }
1566 Thread.futexWaitUncancelable(ptr, expected);
15711567}
15721568
15731569fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void {
15741570 if (builtin.single_threaded) unreachable; // Nothing to wake up.
15751571 const t: *Threaded = @ptrCast(@alignCast(userdata));
15761572 _ = t;
1577 switch (native_os) {
1578 .illumos, .netbsd, .openbsd => @panic("TODO"),
1579 else => Thread.futexWake(ptr, max_waiters),
1580 }
1573 Thread.futexWake(ptr, max_waiters);
15811574}
15821575
15831576const dirCreateDir = switch (native_os) {