@@ -724,13 +724,13 @@ pub fn futex_4arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, timeout
724724 );
725725}
726726
727- /// Given an array of `futex2_waitone `, wait on each uaddr.
727+ /// Given an array of `Futex2.WaitOne `, wait on each uaddr.
728728/// The thread wakes if a futex_wake() is performed at any uaddr.
729729/// The syscall returns immediately if any futex has *uaddr != val.
730730/// timeout is an optional, absolute timeout value for the operation.
731731/// The `flags` argument is for future use and currently should be `.{}`.
732732/// Flags for private futexes, sizes, etc. should be set on the
733- /// individual flags of each `futex2_waitone `.
733+ /// individual flags of each `Futex2.WaitOne `.
734734///
735735/// Returns the array index of one of the woken futexes.
736736/// No further information is provided: any number of other futexes may also
@@ -740,20 +740,21 @@ pub fn futex_4arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, timeout
740740/// most recently woken, nor...)
741741///
742742/// Requires at least kernel v5.16.
743+ // TODO: can't we use slices here? and assert `Futex2.waitone_max`
743744pub fn futex2_waitv (
744- futexes : [* ]const futex2_waitone ,
745- /// Length of `futexes`. Max of FUTEX2_WAITONE_MAX.
746- nr_futexes : u32 ,
747- flags : FUTEX2_FLAGS_WAITV ,
745+ /// The length of `futexes` slice must not exceed `Futex2.waitone_max`
746+ futexes : []const Futex2.WaitOne ,
747+ flags : Futex2.Waitv ,
748748 /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms.
749749 timeout : ? * const kernel_timespec ,
750750 /// Clock to be used for the timeout, realtime or monotonic.
751751 clockid : clockid_t ,
752752) usize {
753+ assert (futexes .len <= Futex2 .waitone_max );
753754 return syscall5 (
754755 .futex_waitv ,
755756 @intFromPtr (futexes ),
756- nr_futexes ,
757+ @intCast ( futexes . len ) ,
757758 @as (u32 , @bitCast (flags )),
758759 @intFromPtr (timeout ),
759760 @intFromEnum (clockid ),
@@ -771,8 +772,8 @@ pub fn futex2_wait(
771772 /// Value of `uaddr`.
772773 val : usize ,
773774 /// Bitmask to match against incoming wakeup masks. Must not be zero.
774- mask : usize ,
775- flags : FUTEX2_FLAGS ,
775+ mask : Futex2.Bitset ,
776+ flags : Futex2.Wait ,
776777 /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms.
777778 timeout : ? * const kernel_timespec ,
778779 /// Clock to be used for the timeout, realtime or monotonic.
@@ -782,7 +783,7 @@ pub fn futex2_wait(
782783 .futex_wait ,
783784 @intFromPtr (uaddr ),
784785 val ,
785- mask ,
786+ @intFromEnum ( mask ) ,
786787 @as (u32 , @bitCast (flags )),
787788 @intFromPtr (timeout ),
788789 @intFromEnum (clockid ),
@@ -798,16 +799,16 @@ pub fn futex2_wake(
798799 /// Futex to wake
799800 uaddr : * const anyopaque ,
800801 /// Bitmask to match against waiters.
801- mask : usize ,
802+ mask : Futex2.Bitset ,
802803 /// Maximum number of waiters on the futex to wake.
803804 nr_wake : i32 ,
804- flags : FUTEX2_FLAGS ,
805+ flags : Futex2.Wake ,
805806) usize {
806807 return syscall4 (
807808 .futex_wake ,
808809 @intFromPtr (uaddr ),
809- mask ,
810- @as ( u32 , @bitCast ( nr_wake ) ),
810+ @intFromEnum ( mask ) ,
811+ @intCast ( nr_wake ),
811812 @as (u32 , @bitCast (flags )),
812813 );
813814}
@@ -816,11 +817,12 @@ pub fn futex2_wake(
816817/// Identical to `FUTEX.CMP_REQUEUE`, except it is part of the futex2 family of calls.
817818///
818819/// Requires at least kernel v6.7.
820+ // TODO: test to ensure I didn't break it
819821pub fn futex2_requeue (
820822 /// The source and destination futexes. Must be a 2-element array.
821- waiters : [ * ] const futex2_waitone ,
823+ waiters : * const [ 2 ] Futex2.WaitOne ,
822824 /// Currently unused.
823- flags : FUTEX2_FLAGS_REQUEUE ,
825+ flags : Futex2.Requeue ,
824826 /// Maximum number of waiters to wake on the source futex.
825827 nr_wake : i32 ,
826828 /// Maximum number of waiters to transfer to the destination futex.
@@ -830,8 +832,8 @@ pub fn futex2_requeue(
830832 .futex_requeue ,
831833 @intFromPtr (waiters ),
832834 @as (u32 , @bitCast (flags )),
833- @as ( u32 , @bitCast ( nr_wake ) ),
834- @as ( u32 , @bitCast ( nr_requeue ) ),
835+ @intCast ( nr_wake ),
836+ @intCast ( nr_requeue ),
835837 );
836838}
837839
@@ -3666,39 +3668,91 @@ pub const FUTEX_WAKE_OP_CMP = enum(u4) {
36663668 GE = 5 ,
36673669};
36683670
3669- /// Max numbers of elements in a `futex2_waitone` array.
3670- pub const FUTEX2_WAITONE_MAX = 128 ;
3671+ pub const Futex2 = struct {
3672+ /// Max numbers of elements in a `futex_waitv` .ie `WaitOne` array
3673+ /// matches FUTEX_WAITV_MAX
3674+ pub const waitone_max = 128 ;
36713675
3672- /// For futex v2 API, the size of the futex at the uaddr. v1 futex are
3673- /// always implicitly U32. As of kernel v6.14, only U32 is implemented
3674- /// for v2 futexes.
3675- pub const FUTEX2_SIZE = enum (u2 ) {
3676- U8 = 0 ,
3677- U16 = 1 ,
3678- U32 = 2 ,
3679- U64 = 3 ,
3680- };
3676+ /// For futex v2 API, the size of the futex at the uaddr. v1 futex are
3677+ /// always implicitly U32. As of kernel v6.14, only U32 is implemented
3678+ /// for v2 futexes.
3679+ pub const Size = enum (u2 ) {
3680+ U8 = 0 ,
3681+ U16 = 1 ,
3682+ U32 = 2 ,
3683+ U64 = 3 ,
3684+ };
36813685
3682- /// As of kernel 6.14 there are no defined flags to futex2_waitv.
3683- pub const FUTEX2_FLAGS_WAITV = packed struct (u32 ) {
3684- _reserved : u32 = 0 ,
3685- };
3686+ /// flags for `futex2_requeue` syscall
3687+ /// As of kernel 6.14 there are no defined flags to futex2_requeue.
3688+ pub const Requeue = packed struct (u32 ) {
3689+ _ : u32 = 0 ,
3690+ };
36863691
3687- /// As of kernel 6.14 there are no defined flags to futex2_requeue.
3688- pub const FUTEX2_FLAGS_REQUEUE = packed struct (u32 ) {
3689- _reserved : u32 = 0 ,
3690- };
3692+ /// flags for `futex2_waitv` syscall
3693+ /// As of kernel 6.14 there are no defined flags to futex2_waitv.
3694+ pub const Waitv = packed struct (u32 ) {
3695+ _ : u32 = 0 ,
3696+ };
36913697
3692- /// Flags for futex v2 APIs (futex2_wait, futex2_wake, futex2_requeue, but
3693- /// not the futex2_waitv syscall, but also used in the futex2_waitone struct).
3694- pub const FUTEX2_FLAGS = packed struct (u32 ) {
3695- size : FUTEX2_SIZE ,
3696- numa : bool = false ,
3697- _reserved : u4 = 0 ,
3698- private : bool ,
3699- _undefined : u24 = 0 ,
3698+ /// flags for `futex2_wait` syscall
3699+ // COMMIT: add mpol and fix private field as its 128 not 32
3700+ pub const Wait = packed struct (u32 ) {
3701+ size : Size ,
3702+ numa : bool = false ,
3703+ mpol : bool = false ,
3704+ _5 : u3 = 0 ,
3705+ private : bool ,
3706+ _9 : u24 = 0 ,
3707+ };
3708+
3709+ /// flags for `futex2_wake` syscall
3710+ pub const Wake = Wait ;
3711+
3712+ /// A waiter for vectorized wait
3713+ /// For `futex2_waitv` and `futex2_requeue`. Arrays of `WaitOne`
3714+ /// allow waiting on multiple futexes in one call.
3715+ /// matches `futex_waitv` in kernel
3716+ pub const WaitOne = extern struct {
3717+ /// Expected value at uaddr, should match size of futex.
3718+ val : u64 ,
3719+ /// User address to wait on. Top-bits must be 0 on 32-bit.
3720+ uaddr : u64 ,
3721+ /// Flags for this waiter.
3722+ flags : Wait ,
3723+ /// Reserved member to preserve data alignment.
3724+ __reserved : u32 = 0 ,
3725+ };
3726+
3727+ pub const Bitset = enum (u64 ) {
3728+ /// matches FUTEX_WAIT_BITSET
3729+ wait = 9 ,
3730+ /// matches FUTEX_WAKE_BITSET
3731+ wake = 10 ,
3732+ /// bitset with all bits set for the FUTEX_xxx_BITSET OPs to request a
3733+ /// match of any bit.
3734+ match_any = 0xffffffff ,
3735+ };
37003736};
37013737
3738+ /// DEPRECATED use `Futex2.WaitOne`
3739+ pub const futex2_waitone = Futex2 .WaitOne ;
3740+
3741+ /// DEPRECATED use constant in `Futex2`
3742+ pub const FUTEX2_WAITONE_MAX = Futex2 .waitone_max ;
3743+
3744+ /// DEPRECATED use `Size` type in `Futex2`
3745+ pub const FUTEX2_SIZE = Futex2 .Size ;
3746+
3747+ /// DEPRECATED use `Waitv` in `Futex2`
3748+ pub const FUTEX2_FLAGS_WAITV = Futex2 .Waitv ;
3749+
3750+ /// DEPRECATED use `Requeue` in `Futex2`
3751+ pub const FUTEX2_FLAGS_REQUEUE = Futex2 .Requeue ;
3752+
3753+ /// DEPRECATED use `Wait` in `Futex2`
3754+ pub const FUTEX2_FLAGS = Futex2 .Wait ;
3755+
37023756pub const PROT = struct {
37033757 /// page can not be accessed
37043758 pub const NONE = 0x0 ;
@@ -9848,19 +9902,6 @@ pub const PTRACE = struct {
98489902 };
98499903};
98509904
9851- /// For futex2_waitv and futex2_requeue. Arrays of `futex2_waitone` allow
9852- /// waiting on multiple futexes in one call.
9853- pub const futex2_waitone = extern struct {
9854- /// Expected value at uaddr, should match size of futex.
9855- val : u64 ,
9856- /// User address to wait on. Top-bits must be 0 on 32-bit.
9857- uaddr : u64 ,
9858- /// Flags for this waiter.
9859- flags : FUTEX2_FLAGS ,
9860- /// Reserved member to preserve alignment.
9861- __reserved : u32 = 0 ,
9862- };
9863-
98649905pub const cache_stat_range = extern struct {
98659906 off : u64 ,
98669907 len : u64 ,
0 commit comments