diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 8dd9ae13fc..21f6840fbe 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -1289,8 +1289,7 @@ fn dirStatPathLinux( var path_buffer: [posix.PATH_MAX]u8 = undefined; const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - const flags: u32 = linux.AT.NO_AUTOMOUNT | - @as(u32, if (!options.follow_symlinks) linux.AT.SYMLINK_NOFOLLOW else 0); + const flags: linux.At = .{ .no_automount = true, .symlink_nofollow = if (!options.follow_symlinks) true else false }; while (true) { try t.checkCancel(); @@ -1299,7 +1298,15 @@ fn dirStatPathLinux( dir.handle, sub_path_posix, flags, - linux.STATX_INO | linux.STATX_SIZE | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, + .{ + .ino = true, + .size = true, + .type = true, + .mode = true, + .atime = true, + .mtime = true, + .ctime = true, + }, &statx, ); switch (linux.errno(rc)) { @@ -1445,8 +1452,16 @@ fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File const rc = linux.statx( file.handle, "", - linux.AT.EMPTY_PATH, - linux.STATX_INO | linux.STATX_SIZE | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, + .{ .empty_path = true }, + .{ + .ino = true, + .size = true, + .type = true, + .mode = true, + .atime = true, + .mtime = true, + .ctime = true, + }, &statx, ); switch (linux.errno(rc)) { @@ -5862,7 +5877,7 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void { .linux => { const linux = std.os.linux; switch (linux.errno(linux.futex_3arg( - &ptr.raw, + ptr, .{ .cmd = .WAKE, .private = true }, @min(max_waiters, std.math.maxInt(i32)), ))) { diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 3257d5f873..7794c4352b 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1216,8 +1216,8 @@ const LinuxThreadImpl = struct { thread: *ThreadCompletion, const ThreadCompletion = struct { - completion: Completion = Completion.init(.running), - child_tid: std.atomic.Value(i32) = std.atomic.Value(i32).init(1), + completion: Completion = .init(.running), + child_tid: std.atomic.Value(i32) = .init(1), parent_tid: i32 = undefined, mapped: []align(std.heap.page_size_min) u8, @@ -1662,7 +1662,7 @@ const LinuxThreadImpl = struct { if (tid == 0) break; switch (linux.errno(linux.futex_4arg( - @ptrCast(&self.thread.child_tid.raw), + @ptrCast(&self.thread.child_tid), .{ .cmd = .WAIT, .private = false }, @bitCast(tid), null, diff --git a/lib/std/Thread/Futex.zig b/lib/std/Thread/Futex.zig index b61062c361..3f4cdda5bf 100644 --- a/lib/std/Thread/Futex.zig +++ b/lib/std/Thread/Futex.zig @@ -263,7 +263,7 @@ const LinuxImpl = struct { } const rc = linux.futex_4arg( - &ptr.raw, + ptr, .{ .cmd = .WAIT, .private = true }, expect, if (timeout != null) &ts else null, @@ -285,7 +285,7 @@ const LinuxImpl = struct { fn wake(ptr: *const atomic.Value(u32), max_waiters: u32) void { const rc = linux.futex_3arg( - &ptr.raw, + ptr, .{ .cmd = .WAKE, .private = true }, @min(max_waiters, std.math.maxInt(i32)), ); diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index cbba463ffb..8948bec2b2 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -4,6 +4,7 @@ //! * Implement all the syscalls in the same way that libc functions will //! provide `rename` when only the `renameat` syscall exists. const std = @import("../std.zig"); +const atomic = std.atomic; const builtin = @import("builtin"); const assert = std.debug.assert; const maxInt = std.math.maxInt; @@ -754,7 +755,7 @@ pub const futex_param4 = extern union { /// The futex_op parameter is a sub-command and flags. The sub-command /// defines which of the subsequent paramters are relevant. pub fn futex( - uaddr: *const u32, + uaddr: *const atomic.Value(u32), futex_op: FUTEX_OP, val: u32, val2timeout: futex_param4, @@ -774,7 +775,7 @@ pub fn futex( /// Three-argument variation of the v1 futex call. Only suitable for a /// futex_op that ignores the remaining arguments (e.g., FUTUX_OP.WAKE). -pub fn futex_3arg(uaddr: *const u32, futex_op: FUTEX_OP, val: u32) usize { +pub fn futex_3arg(uaddr: *const atomic.Value(u32), futex_op: FUTEX_OP, val: u32) usize { return syscall3( if (@hasField(SYS, "futex") and native_arch != .hexagon) .futex else .futex_time64, @intFromPtr(uaddr), @@ -785,7 +786,7 @@ pub fn futex_3arg(uaddr: *const u32, futex_op: FUTEX_OP, val: u32) usize { /// Four-argument variation on the v1 futex call. Only suitable for /// futex_op that ignores the remaining arguments (e.g., FUTEX_OP.WAIT). -pub fn futex_4arg(uaddr: *const u32, futex_op: FUTEX_OP, val: u32, timeout: ?*const timespec) usize { +pub fn futex_4arg(uaddr: *const atomic.Value(u32), futex_op: FUTEX_OP, val: u32, timeout: ?*const timespec) usize { return syscall4( if (@hasField(SYS, "futex") and native_arch != .hexagon) .futex else .futex_time64, @intFromPtr(uaddr), @@ -838,7 +839,7 @@ pub fn futex2_waitv( /// Requires at least kernel v6.7. pub fn futex2_wait( /// Address of the futex to wait on. - uaddr: *const u32, + uaddr: *const atomic.Value(u32), /// Value of `uaddr`. val: usize, /// Bitmask to match against incoming wakeup masks. Must not be zero. @@ -867,7 +868,7 @@ pub fn futex2_wait( /// Requires at least kernel v6.7. pub fn futex2_wake( /// Futex to wake - uaddr: *const u32, + uaddr: *const atomic.Value(u32), /// Bitmask to match against waiters. mask: Futex2.Bitset, /// Maximum number of waiters on the futex to wake. diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig index e568848260..8d201e5a6f 100644 --- a/lib/std/os/linux/IoUring.zig +++ b/lib/std/os/linux/IoUring.zig @@ -1694,7 +1694,7 @@ pub fn socket( domain: linux.Af, socket_type: linux.Sock, protocol: linux.IpProto, - /// flags is unused + /// flags are currently unused flags: u32, ) !*Sqe { const sqe = try self.get_sqe(); @@ -1711,7 +1711,7 @@ pub fn socket_direct( domain: linux.Af, socket_type: linux.Sock, protocol: linux.IpProto, - /// flags is unused + /// flags are currently unused flags: u32, file_index: u32, ) !*Sqe { @@ -1731,7 +1731,7 @@ pub fn socket_direct_alloc( domain: linux.Af, socket_type: linux.Sock, protocol: linux.IpProto, - /// flags unused + /// flags are currently unused flags: u32, ) !*Sqe { const sqe = try self.get_sqe(); @@ -5377,8 +5377,8 @@ test "timeout (after a relative time)" { }; defer ring.deinit(); - const ms = 10; - const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1000000 }; + const ms = 5; + const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1_000_000 }; const started = try std.Io.Clock.awake.now(io); const sqe = try ring.timeout(0x55555555, &ts, 0, .{}); @@ -5394,9 +5394,9 @@ test "timeout (after a relative time)" { }, cqe); // Tests should not depend on timings: skip test if outside margin. - const margin = 5; + const ms_margin = 5; const ms_elapsed = started.durationTo(stopped).toMilliseconds(); - if (ms_elapsed > margin) return error.SkipZigTest; + if (ms_elapsed > ms_margin) return error.SkipZigTest; } test "timeout (after a number of completions)" { @@ -5802,7 +5802,7 @@ test "shutdown" { // Socket bound, expect shutdown to work { // TODO: update posix later to use Typed Flags - const server = try posix.socket(address.any.family, @as(u32, @bitCast(linux.Sock{ .type = .stream, .flags = .{ .cloexec = true } })), 0); + const server = try posix.socket(address.family, @as(u32, @bitCast(linux.Sock{ .type = .stream, .flags = .{ .cloexec = true } })), 0); defer posix.close(server); try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(u32, 1))); try posix.bind(server, addrAny(&address), @sizeOf(linux.sockaddr.in)); @@ -7460,7 +7460,7 @@ test "bind/listen/connect" { const listen_fd = brk: { // Create socket - _ = try ring.socket(1, @enumFromInt(addr.any.family), .{ .type = .stream, .flags = .{ .cloexec = true } }, @enumFromInt(proto), 0); + _ = try ring.socket(1, @enumFromInt(addr.family), .{ .type = .stream, .flags = .{ .cloexec = true } }, @enumFromInt(proto), 0); try testing.expectEqual(1, try ring.submit()); var cqe = try ring.copy_cqe(); try testing.expectEqual(1, cqe.user_data); @@ -7472,7 +7472,7 @@ test "bind/listen/connect" { var optval: u32 = 1; (try ring.setsockopt(2, listen_fd, .socket, .reuseaddr, mem.asBytes(&optval))).link_next(); (try ring.setsockopt(3, listen_fd, .socket, .reuseport, mem.asBytes(&optval))).link_next(); - (try ring.bind(4, listen_fd, addrAny(&addr), @sizeOf(linux.sockaddr.in), 0)).link_next(); + (try ring.bind(4, listen_fd, addrAny(&addr), @sizeOf(linux.sockaddr.in))).link_next(); _ = try ring.listen(5, listen_fd, 1); // Submit 4 operations try testing.expectEqual(4, try ring.submit()); diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index fffc8abec3..c0db602110 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -200,28 +200,28 @@ test "futex v1" { var rc: usize = 0; // No-op wait, lock value is not expected value - rc = linux.futex(&lock.raw, .{ .cmd = .WAIT, .private = true }, 2, .{ .timeout = null }, null, 0); + rc = linux.futex(&lock, .{ .cmd = .WAIT, .private = true }, 2, .{ .timeout = null }, null, 0); try expectEqual(.AGAIN, linux.errno(rc)); - rc = linux.futex_4arg(&lock.raw, .{ .cmd = .WAIT, .private = true }, 2, null); + rc = linux.futex_4arg(&lock, .{ .cmd = .WAIT, .private = true }, 2, null); try expectEqual(.AGAIN, linux.errno(rc)); // Short-fuse wait, timeout kicks in - rc = linux.futex(&lock.raw, .{ .cmd = .WAIT, .private = true }, 1, .{ .timeout = &.{ .sec = 0, .nsec = 2 } }, null, 0); + rc = linux.futex(&lock, .{ .cmd = .WAIT, .private = true }, 1, .{ .timeout = &.{ .sec = 0, .nsec = 2 } }, null, 0); try expectEqual(.TIMEDOUT, linux.errno(rc)); - rc = linux.futex_4arg(&lock.raw, .{ .cmd = .WAIT, .private = true }, 1, &.{ .sec = 0, .nsec = 2 }); + rc = linux.futex_4arg(&lock, .{ .cmd = .WAIT, .private = true }, 1, &.{ .sec = 0, .nsec = 2 }); try expectEqual(.TIMEDOUT, linux.errno(rc)); // Wakeup (no waiters) - rc = linux.futex(&lock.raw, .{ .cmd = .WAKE, .private = true }, 2, .{ .timeout = null }, null, 0); + rc = linux.futex(&lock, .{ .cmd = .WAKE, .private = true }, 2, .{ .timeout = null }, null, 0); try expectEqual(0, rc); - rc = linux.futex_3arg(&lock.raw, .{ .cmd = .WAKE, .private = true }, 2); + rc = linux.futex_3arg(&lock, .{ .cmd = .WAKE, .private = true }, 2); try expectEqual(0, rc); // CMP_REQUEUE - val3 mismatch - rc = linux.futex(&lock.raw, .{ .cmd = .CMP_REQUEUE, .private = true }, 2, .{ .val2 = 0 }, null, 99); + rc = linux.futex(&lock, .{ .cmd = .CMP_REQUEUE, .private = true }, 2, .{ .val2 = 0 }, null, 99); try expectEqual(.AGAIN, linux.errno(rc)); // CMP_REQUEUE - requeue (but no waiters, so ... not much) @@ -229,14 +229,14 @@ test "futex v1" { const val3 = 1; const wake_nr = 3; const requeue_max = std.math.maxInt(u31); - var target_lock: std.atomic.Value(u32) = .init(1); - rc = linux.futex(&lock.raw, .{ .cmd = .CMP_REQUEUE, .private = true }, wake_nr, .{ .val2 = requeue_max }, &target_lock.raw, val3); + const target_lock: std.atomic.Value(u32) = .init(1); + rc = linux.futex(&lock, .{ .cmd = .CMP_REQUEUE, .private = true }, wake_nr, .{ .val2 = requeue_max }, &target_lock, val3); try expectEqual(0, rc); } // WAKE_OP - just to see if we can construct the arguments ... { - var lock2: std.atomic.Value(u32) = .init(1); + const lock2: std.atomic.Value(u32) = .init(1); const wake1_nr = 2; const wake2_nr = 3; const wake_op = linux.FUTEX_WAKE_OP{ @@ -247,29 +247,29 @@ test "futex v1" { .cmdarg = 5, }; - rc = linux.futex(&lock.raw, .{ .cmd = .WAKE_OP, .private = true }, wake1_nr, .{ .val2 = wake2_nr }, &lock2.raw, @bitCast(wake_op)); + rc = linux.futex(&lock, .{ .cmd = .WAKE_OP, .private = true }, wake1_nr, .{ .val2 = wake2_nr }, &lock2, @bitCast(wake_op)); try expectEqual(0, rc); } // WAIT_BITSET { // val1 return early - rc = linux.futex(&lock.raw, .{ .cmd = .WAIT_BITSET, .private = true }, 2, .{ .timeout = null }, null, 0xfff); + rc = linux.futex(&lock, .{ .cmd = .WAIT_BITSET, .private = true }, 2, .{ .timeout = null }, null, 0xfff); try expectEqual(.AGAIN, linux.errno(rc)); // timeout wait const timeout: linux.timespec = .{ .sec = 0, .nsec = 2 }; - rc = linux.futex(&lock.raw, .{ .cmd = .WAIT_BITSET, .private = true }, 1, .{ .timeout = &timeout }, null, 0xfff); + rc = linux.futex(&lock, .{ .cmd = .WAIT_BITSET, .private = true }, 1, .{ .timeout = &timeout }, null, 0xfff); try expectEqual(.TIMEDOUT, linux.errno(rc)); } // WAKE_BITSET { - rc = linux.futex(&lock.raw, .{ .cmd = .WAKE_BITSET, .private = true }, 2, .{ .timeout = null }, null, 0xfff000); + rc = linux.futex(&lock, .{ .cmd = .WAKE_BITSET, .private = true }, 2, .{ .timeout = null }, null, 0xfff000); try expectEqual(0, rc); // bitmask must have at least 1 bit set: - rc = linux.futex(&lock.raw, .{ .cmd = .WAKE_BITSET, .private = true }, 2, .{ .timeout = null }, null, 0); + rc = linux.futex(&lock, .{ .cmd = .WAKE_BITSET, .private = true }, 2, .{ .timeout = null }, null, 0); try expectEqual(.INVAL, linux.errno(rc)); } } @@ -289,17 +289,17 @@ test "futex2_waitv" { const futexes: [3]linux.Futex2.WaitOne = .{ .{ .val = 1, - .uaddr = @intFromPtr(&locks[0].raw), + .uaddr = @intFromPtr(&locks[0]), .flags = .{ .size = .U32, .private = true }, }, .{ .val = 1, - .uaddr = @intFromPtr(&locks[1].raw), + .uaddr = @intFromPtr(&locks[1]), .flags = .{ .size = .U32, .private = true }, }, .{ .val = 1, - .uaddr = @intFromPtr(&locks[2].raw), + .uaddr = @intFromPtr(&locks[2]), .flags = .{ .size = .U32, .private = true }, }, }; @@ -316,7 +316,7 @@ test "futex2_waitv" { // Futex v2 API is only supported on recent kernels (v6.7), so skip tests if the syscalls // return ENOSYS. fn futex2_skip_if_unsupported() !void { - const lock: u32 = 0; + const lock: std.atomic.Value(u32) = .init(0); const rc = linux.futex2_wake(&lock, .empty, 1, .{ .size = .U32, .private = true }); if (linux.errno(rc) == .NOSYS) { return error.SkipZigTest; @@ -324,7 +324,7 @@ fn futex2_skip_if_unsupported() !void { } test "futex2_wait" { - var lock: std.atomic.Value(u32) = .init(1); + const lock: std.atomic.Value(u32) = .init(1); var rc: usize = 0; const mask: linux.Futex2.Bitset = .{ .waiter1 = true }; @@ -333,23 +333,23 @@ test "futex2_wait" { // The API for 8,16,64 bit futexes is defined, but as of kernel v6.14 // (at least) they're not implemented. if (false) { - rc = linux.futex2_wait(&lock.raw, 1, mask, .{ .size = .U8, .private = true }, null, .MONOTONIC); + rc = linux.futex2_wait(&lock, 1, mask, .{ .size = .U8, .private = true }, null, .MONOTONIC); try expectEqual(.INVAL, linux.errno(rc)); - rc = linux.futex2_wait(&lock.raw, 1, mask, .{ .size = .U16, .private = true }, null, .MONOTONIC); + rc = linux.futex2_wait(&lock, 1, mask, .{ .size = .U16, .private = true }, null, .MONOTONIC); try expectEqual(.INVAL, linux.errno(rc)); - rc = linux.futex2_wait(&lock.raw, 1, mask, .{ .size = .U64, .private = true }, null, .MONOTONIC); + rc = linux.futex2_wait(&lock, 1, mask, .{ .size = .U64, .private = true }, null, .MONOTONIC); try expectEqual(.INVAL, linux.errno(rc)); } const flags: linux.Futex2.Wait = .{ .size = .U32, .private = true }; // no-wait, lock state mismatch - rc = linux.futex2_wait(&lock.raw, 2, mask, flags, null, .MONOTONIC); + rc = linux.futex2_wait(&lock, 2, mask, flags, null, .MONOTONIC); try expectEqual(.AGAIN, linux.errno(rc)); // hit timeout on wait - rc = linux.futex2_wait(&lock.raw, 1, mask, flags, &.{ .sec = 0, .nsec = 2 }, .MONOTONIC); + rc = linux.futex2_wait(&lock, 1, mask, flags, &.{ .sec = 0, .nsec = 2 }, .MONOTONIC); try expectEqual(.TIMEDOUT, linux.errno(rc)); // timeout is absolute @@ -363,20 +363,20 @@ test "futex2_wait" { .sec = curr.sec, .nsec = curr.nsec + 2, }; - rc = linux.futex2_wait(&lock.raw, 1, mask, flags, &timeout, .MONOTONIC); + rc = linux.futex2_wait(&lock, 1, mask, flags, &timeout, .MONOTONIC); try expectEqual(.TIMEDOUT, linux.errno(rc)); } - rc = linux.futex2_wait(&lock.raw, 1, mask, flags, &.{ .sec = 0, .nsec = 2 }, .REALTIME); + rc = linux.futex2_wait(&lock, 1, mask, flags, &.{ .sec = 0, .nsec = 2 }, .REALTIME); try expectEqual(.TIMEDOUT, linux.errno(rc)); } test "futex2_wake" { - var lock: std.atomic.Value(u32) = .init(1); + const lock: std.atomic.Value(u32) = .init(1); try futex2_skip_if_unsupported(); - const rc = linux.futex2_wake(&lock.raw, .fromInt(0xFF), 1, .{ .size = .U32, .private = true }); + const rc = linux.futex2_wake(&lock, .fromInt(0xFF), 1, .{ .size = .U32, .private = true }); try expectEqual(0, rc); } @@ -391,12 +391,12 @@ test "futex2_requeue" { const futexes: [2]linux.Futex2.WaitOne = .{ .{ .val = 1, - .uaddr = @intFromPtr(&locks[0].raw), + .uaddr = @intFromPtr(&locks[0]), .flags = .{ .size = .U32, .private = true }, }, .{ .val = 1, - .uaddr = @intFromPtr(&locks[1].raw), + .uaddr = @intFromPtr(&locks[1]), .flags = .{ .size = .U32, .private = true }, }, }; diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 13d16ea324..f5923116e4 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -3992,7 +3992,7 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat; var stat = mem.zeroes(Stat); - switch (errno(fstatat_sym(dirfd, pathname, &stat, flags))) { + switch (errno(fstatat_sym(dirfd, pathname, &stat, @bitCast(flags)))) { .SUCCESS => return stat, .INVAL => unreachable, .BADF => unreachable, // Always a race condition.