@@ -690,7 +690,14 @@ pub const futex_param4 = extern union {
690690///
691691/// The futex_op parameter is a sub-command and flags. The sub-command
692692/// defines which of the subsequent paramters are relevant.
693- pub fn futex (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 , val2timeout : futex_param4 , uaddr2 : ? * const anyopaque , val3 : u32 ) usize {
693+ pub fn futex (
694+ uaddr : * const u32 ,
695+ futex_op : FUTEX_OP ,
696+ val : u32 ,
697+ val2timeout : futex_param4 ,
698+ uaddr2 : ? * const anyopaque ,
699+ val3 : u32 ,
700+ ) usize {
694701 return syscall6 (
695702 if (@hasField (SYS , "futex" ) and native_arch != .hexagon ) .futex else .futex_time64 ,
696703 @intFromPtr (uaddr ),
@@ -704,7 +711,7 @@ pub fn futex(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, val2timeout:
704711
705712/// Three-argument variation of the v1 futex call. Only suitable for a
706713/// futex_op that ignores the remaining arguments (e.g., FUTUX_OP.WAKE).
707- pub fn futex_3arg (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 ) usize {
714+ pub fn futex_3arg (uaddr : * const u32 , futex_op : FUTEX_OP , val : u32 ) usize {
708715 return syscall3 (
709716 if (@hasField (SYS , "futex" ) and native_arch != .hexagon ) .futex else .futex_time64 ,
710717 @intFromPtr (uaddr ),
@@ -715,7 +722,7 @@ pub fn futex_3arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32) usize {
715722
716723/// Four-argument variation on the v1 futex call. Only suitable for
717724/// futex_op that ignores the remaining arguments (e.g., FUTEX_OP.WAIT).
718- pub fn futex_4arg (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 , timeout : ? * const timespec ) usize {
725+ pub fn futex_4arg (uaddr : * const u32 , futex_op : FUTEX_OP , val : u32 , timeout : ? * const timespec ) usize {
719726 return syscall4 (
720727 if (@hasField (SYS , "futex" ) and native_arch != .hexagon ) .futex else .futex_time64 ,
721728 @intFromPtr (uaddr ),
@@ -754,7 +761,7 @@ pub fn futex2_waitv(
754761 assert (futexes .len <= Futex2 .waitone_max );
755762 return syscall5 (
756763 .futex_waitv ,
757- @intFromPtr (futexes ),
764+ @intFromPtr (futexes . ptr ),
758765 @intCast (futexes .len ),
759766 @as (u32 , @bitCast (flags )),
760767 @intFromPtr (timeout ),
@@ -769,7 +776,7 @@ pub fn futex2_waitv(
769776/// Requires at least kernel v6.7.
770777pub fn futex2_wait (
771778 /// Address of the futex to wait on.
772- uaddr : * const anyopaque ,
779+ uaddr : * const u32 ,
773780 /// Value of `uaddr`.
774781 val : usize ,
775782 /// Bitmask to match against incoming wakeup masks. Must not be zero.
@@ -784,7 +791,7 @@ pub fn futex2_wait(
784791 .futex_wait ,
785792 @intFromPtr (uaddr ),
786793 val ,
787- @intFromEnum (mask ),
794+ @intCast (mask . toInt () ),
788795 @as (u32 , @bitCast (flags )),
789796 @intFromPtr (timeout ),
790797 @intFromEnum (clockid ),
@@ -798,7 +805,7 @@ pub fn futex2_wait(
798805/// Requires at least kernel v6.7.
799806pub fn futex2_wake (
800807 /// Futex to wake
801- uaddr : * const anyopaque ,
808+ uaddr : * const u32 ,
802809 /// Bitmask to match against waiters.
803810 mask : Futex2.Bitset ,
804811 /// Maximum number of waiters on the futex to wake.
@@ -808,7 +815,7 @@ pub fn futex2_wake(
808815 return syscall4 (
809816 .futex_wake ,
810817 @intFromPtr (uaddr ),
811- @intFromEnum (mask ),
818+ @intCast (mask . toInt () ),
812819 @intCast (nr_wake ),
813820 @as (u32 , @bitCast (flags )),
814821 );
@@ -2280,16 +2287,27 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
22802287 }
22812288}
22822289
2283- // TODO: flags is At Flags
2284- pub fn fstatat (dirfd : i32 , path : [* :0 ]const u8 , stat_buf : * Stat , flags : u32 ) usize {
2290+ pub fn fstatat (dirfd : i32 , path : [* :0 ]const u8 , stat_buf : * Stat , flags : At ) usize {
22852291 if (native_arch == .riscv32 or native_arch .isLoongArch ()) {
22862292 // riscv32 and loongarch have made the interesting decision to not implement some of
22872293 // the older stat syscalls, including this one.
22882294 @compileError ("No fstatat syscall on this architecture." );
22892295 } else if (@hasField (SYS , "fstatat64" )) {
2290- return syscall4 (.fstatat64 , @as (usize , @bitCast (@as (isize , dirfd ))), @intFromPtr (path ), @intFromPtr (stat_buf ), flags );
2296+ return syscall4 (
2297+ .fstatat64 ,
2298+ @as (usize , @bitCast (@as (isize , dirfd ))),
2299+ @intFromPtr (path ),
2300+ @intFromPtr (stat_buf ),
2301+ @intCast (@as (u32 , @bitCast (flags ))),
2302+ );
22912303 } else {
2292- return syscall4 (.fstatat , @as (usize , @bitCast (@as (isize , dirfd ))), @intFromPtr (path ), @intFromPtr (stat_buf ), flags );
2304+ return syscall4 (
2305+ .fstatat ,
2306+ @as (usize , @bitCast (@as (isize , dirfd ))),
2307+ @intFromPtr (path ),
2308+ @intFromPtr (stat_buf ),
2309+ @bitCast (flags ),
2310+ );
22932311 }
22942312}
22952313
@@ -2459,8 +2477,14 @@ pub fn epoll_create1(flags: usize) usize {
24592477 return syscall1 (.epoll_create1 , flags );
24602478}
24612479
2462- pub fn epoll_ctl (epoll_fd : i32 , op : u32 , fd : i32 , ev : ? * epoll_event ) usize {
2463- return syscall4 (.epoll_ctl , @as (usize , @bitCast (@as (isize , epoll_fd ))), @as (usize , @intCast (op )), @as (usize , @bitCast (@as (isize , fd ))), @intFromPtr (ev ));
2480+ pub fn epoll_ctl (epoll_fd : i32 , op : EpollOp , fd : i32 , ev : ? * epoll_event ) usize {
2481+ return syscall4 (
2482+ .epoll_ctl ,
2483+ @as (usize , @bitCast (@as (isize , epoll_fd ))),
2484+ @as (usize , @intFromEnum (op )),
2485+ @as (usize , @bitCast (@as (isize , fd ))),
2486+ @intFromPtr (ev ),
2487+ );
24642488}
24652489
24662490pub fn epoll_wait (epoll_fd : i32 , events : [* ]epoll_event , maxevents : u32 , timeout : i32 ) usize {
@@ -3733,14 +3757,67 @@ pub const Futex2 = struct {
37333757 __reserved : u32 = 0 ,
37343758 };
37353759
3736- pub const Bitset = enum (u64 ) {
3737- /// matches FUTEX_WAIT_BITSET
3738- wait = 9 ,
3739- /// matches FUTEX_WAKE_BITSET
3740- wake = 10 ,
3741- /// bitset with all bits set for the FUTEX_xxx_BITSET OPs to request a
3742- /// match of any bit.
3743- match_any = 0xffffffff ,
3760+ /// `Bitset` for `futex2_wait`, `futex2_wake`, `IoUring.futex_wait` and
3761+ /// `IoUring.futex_wake` operations
3762+ /// At least one bit must be set before performing supported operations
3763+ /// The bitset is stored in the kernel-internal state of a waiter. During a
3764+ /// wake operation, the same mask previously set during the wait call can
3765+ /// be used to select which waiters to woke up
3766+ /// See https://man7.org/linux/man-pages/man2/futex_wake_bitset.2const.html
3767+ /// `IoUring` supports a u64 `Bitset` while the raw syscalls uses only u32
3768+ /// bits of `Bitset`
3769+ pub const Bitset = packed struct (u64 ) {
3770+ waiter1 : bool = false ,
3771+ waiter2 : bool = false ,
3772+ waiter3 : bool = false ,
3773+ waiter4 : bool = false ,
3774+ waiter5 : bool = false ,
3775+ waiter6 : bool = false ,
3776+ waiter7 : bool = false ,
3777+ waiter8 : bool = false ,
3778+ waiter9 : bool = false ,
3779+ waiter10 : bool = false ,
3780+ waiter11 : bool = false ,
3781+ waiter12 : bool = false ,
3782+ waiter13 : bool = false ,
3783+ waiter14 : bool = false ,
3784+ waiter15 : bool = false ,
3785+ waiter16 : bool = false ,
3786+ waiter17 : bool = false ,
3787+ waiter18 : bool = false ,
3788+ waiter19 : bool = false ,
3789+ waiter20 : bool = false ,
3790+ waiter21 : bool = false ,
3791+ waiter22 : bool = false ,
3792+ waiter23 : bool = false ,
3793+ waiter24 : bool = false ,
3794+ waiter25 : bool = false ,
3795+ waiter26 : bool = false ,
3796+ waiter27 : bool = false ,
3797+ waiter28 : bool = false ,
3798+ waiter29 : bool = false ,
3799+ waiter30 : bool = false ,
3800+ waiter31 : bool = false ,
3801+ waiter32 : bool = false ,
3802+ io_uring_extra : u32 = 0 ,
3803+
3804+ /// `Bitset` with all bits set for the FUTEX_xxx_BITSET OPs to request a
3805+ /// match of any bit. matches FUTEX_BITSET_MATCH_ANY
3806+ pub const match_any : Bitset = @bitCast (@as (u64 , 0x00000000ffffffff ));
3807+ /// Bitset must not be empty, this is only useful in test
3808+ pub const empty : Bitset = .{};
3809+
3810+ /// Create from raw u64 value
3811+ pub fn fromInt (value : u64 ) Bitset {
3812+ const bitset : Bitset = @bitCast (value );
3813+ assert (bitset != empty );
3814+ return bitset ;
3815+ }
3816+
3817+ /// Convert to raw u64 for syscall
3818+ pub fn toInt (self : Bitset ) u64 {
3819+ return @bitCast (self );
3820+ }
37443821 };
37453822};
37463823
0 commit comments