@@ -679,56 +679,55 @@ pub fn futex_4arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, timeout
679
679
680
680
/// Given an array of `futex_waitv`, wait on each uaddr.
681
681
/// The thread wakes if a futex_wake() is performed at any uaddr.
682
- /// The syscall returns immediately if any waiter has *uaddr != val.
683
- /// timeout is an optional timeout value for the operation.
684
- /// Each waiter has individual flags.
685
- /// The `flags` argument for the syscall should be used solely for specifying
686
- /// the timeout as realtime, if needed.
687
- /// Flags for private futexes, sizes, etc. should be used on the
688
- /// individual flags of each waiter.
682
+ /// The syscall returns immediately if any futex has *uaddr != val.
683
+ /// timeout is an optional, absolute timeout value for the operation.
684
+ /// The `flags` argument is for future use and currently should be `.{}`.
685
+ /// Flags for private futexes, sizes, etc. should be set on the
686
+ /// individual flags of each futex.
689
687
///
690
688
/// Returns the array index of one of the woken futexes.
691
689
/// No further information is provided: any number of other futexes may also
692
690
/// have been woken by the same event, and if more than one futex was woken,
693
691
/// the returned index may refer to any one of them.
694
692
/// (It is not necessaryily the futex with the smallest index, nor the one
695
693
/// most recently woken, nor...)
694
+ ///
695
+ /// Requires at least kernel v5.16
696
696
pub fn futex2_waitv (
697
- /// List of futexes to wait on.
698
- waiters : [* ]futex_waitv ,
699
- /// Length of `waiters`.
697
+ futexes : [* ]const futex_waitv ,
698
+ /// Length of `futexes`. Max of FUTEX2_WAITV_MAX.
700
699
nr_futexes : u32 ,
701
- /// Flag for timeout (monotonic/realtime).
702
- flags : u32 ,
703
- /// Optional absolute timeout.
704
- timeout : ? * const timespec ,
700
+ flags : FUTEX2_FLAGS_WAITV ,
701
+ /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms.
702
+ timeout : ? * const kernel_timespec ,
705
703
/// Clock to be used for the timeout, realtime or monotonic.
706
704
clockid : clockid_t ,
707
705
) usize {
708
706
return syscall5 (
709
707
.futex_waitv ,
710
- @intFromPtr (waiters ),
708
+ @intFromPtr (futexes ),
711
709
nr_futexes ,
712
- flags ,
710
+ @as ( u32 , @bitCast ( flags )) ,
713
711
@intFromPtr (timeout ),
714
- @bitCast ( @as ( isize , @ intFromEnum (clockid )) ),
712
+ @intFromEnum (clockid ),
715
713
);
716
714
}
717
715
718
- /// Wait on a futex.
719
- /// Identical to the traditional `FUTEX.FUTEX_WAIT_BITSET` op, except it is part of the
720
- /// futex2 familiy of calls.
716
+ /// Wait on a single futex.
717
+ /// Identical to the futex v1 `FUTEX.FUTEX_WAIT_BITSET` op, except it is part of the
718
+ /// futex2 family of calls.
719
+ ///
720
+ /// Requires at least kernel v6.7.
721
721
pub fn futex2_wait (
722
722
/// Address of the futex to wait on.
723
723
uaddr : * const anyopaque ,
724
724
/// Value of `uaddr`.
725
725
val : usize ,
726
- /// Bitmask.
726
+ /// Bitmask to match against incoming wakeup masks. Must not be zero .
727
727
mask : usize ,
728
- /// `FUTEX2` flags.
729
- flags : u32 ,
730
- /// Optional absolute timeout.
731
- timeout : ? * const timespec ,
728
+ flags : FUTEX2_FLAGS ,
729
+ /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms.
730
+ timeout : ? * const kernel_timespec ,
732
731
/// Clock to be used for the timeout, realtime or monotonic.
733
732
clockid : clockid_t ,
734
733
) usize {
@@ -737,52 +736,55 @@ pub fn futex2_wait(
737
736
@intFromPtr (uaddr ),
738
737
val ,
739
738
mask ,
740
- flags ,
739
+ @as ( u32 , @bitCast ( flags )) ,
741
740
@intFromPtr (timeout ),
742
- @bitCast ( @as ( isize , @ intFromEnum (clockid )) ),
741
+ @intFromEnum (clockid ),
743
742
);
744
743
}
745
744
746
- /// Wake a number of futexes .
747
- /// Identical to the traditional `FUTEX.FUTEX_WAIT_BITSET ` op, except it is part of the
745
+ /// Wake (subset of) waiters on given futex .
746
+ /// Identical to the traditional `FUTEX.FUTEX_WAKE_BITSET ` op, except it is part of the
748
747
/// futex2 family of calls.
748
+ ///
749
+ /// Requires at least kernel v6.7.
749
750
pub fn futex2_wake (
750
- /// Address of the futex(es) to wake.
751
+ /// Futex to wake
751
752
uaddr : * const anyopaque ,
752
- /// Bitmask
753
+ /// Bitmask to match against waiters.
753
754
mask : usize ,
754
- /// Number of the futexes to wake.
755
- nr : i32 ,
756
- /// `FUTEX2` flags.
757
- flags : u32 ,
755
+ /// Maximum number of waiters on the futex to wake.
756
+ nr_wake : i32 ,
757
+ flags : FUTEX2_FLAGS ,
758
758
) usize {
759
759
return syscall4 (
760
760
.futex_wake ,
761
761
@intFromPtr (uaddr ),
762
762
mask ,
763
- @bitCast ( @ as (isize , nr )),
764
- flags ,
763
+ @as (u32 , @bitCast ( nr_wake )),
764
+ @as ( u32 , @bitCast ( flags )) ,
765
765
);
766
766
}
767
767
768
- /// Requeue a waiter from one futex to another.
768
+ /// Wake and/or requeue waiter(s) from one futex to another.
769
769
/// Identical to `FUTEX.CMP_REQUEUE`, except it is part of the futex2 family of calls.
770
+ ///
771
+ /// Requires at least kernel v6.7.
770
772
pub fn futex2_requeue (
771
- /// Array describing the source and destination futex .
772
- waiters : [* ]futex_waitv ,
773
- /// Unused .
774
- flags : u32 ,
775
- /// Number of futexes to wake.
773
+ /// The source and destination futexes. Must be a 2-element array .
774
+ waiters : [* ]const futex_waitv ,
775
+ /// Currently unused .
776
+ flags : FUTEX2_FLAGS_REQUEUE ,
777
+ /// Maximum number of waiters to wake on the source futex .
776
778
nr_wake : i32 ,
777
- /// Number of futexes to requeue .
779
+ /// Maximum number of waiters to transfer to the destination futex .
778
780
nr_requeue : i32 ,
779
781
) usize {
780
782
return syscall4 (
781
783
.futex_requeue ,
782
784
@intFromPtr (waiters ),
783
- flags ,
784
- @bitCast ( @ as (isize , nr_wake )),
785
- @bitCast ( @ as (isize , nr_requeue )),
785
+ @as ( u32 , @bitCast ( flags )) ,
786
+ @as (u32 , @bitCast ( nr_wake )),
787
+ @as (u32 , @bitCast ( nr_requeue )),
786
788
);
787
789
}
788
790
@@ -3275,16 +3277,6 @@ pub const FALLOC = struct {
3275
3277
pub const FL_UNSHARE_RANGE = 0x40 ;
3276
3278
};
3277
3279
3278
- pub const FUTEX2 = struct {
3279
- pub const SIZE_U8 = 0x00 ;
3280
- pub const SIZE_U16 = 0x01 ;
3281
- pub const SIZE_U32 = 0x02 ;
3282
- pub const SIZE_U64 = 0x03 ;
3283
- pub const NUMA = 0x04 ;
3284
-
3285
- pub const PRIVATE = FUTEX .PRIVATE_FLAG ;
3286
- };
3287
-
3288
3280
// Futex v1 API commands. See futex man page for each command's
3289
3281
// interpretation of the futex arguments.
3290
3282
pub const FUTEX_COMMAND = enum (u7 ) {
@@ -3348,6 +3340,36 @@ pub const FUTEX_WAKE_OP_CMP = enum(u4) {
3348
3340
/// Max numbers of elements in a `futex_waitv` array.
3349
3341
pub const FUTEX2_WAITV_MAX = 128 ;
3350
3342
3343
+ /// For futex v2 API, the size of the futex at the uaddr. v1 futex are
3344
+ /// always implicitly U32. As of kernel v6.14, only U32 is implemented
3345
+ /// for v2 futexes.
3346
+ pub const FUTEX2_SIZE = enum (u2 ) {
3347
+ U8 = 0 ,
3348
+ U16 = 1 ,
3349
+ U32 = 2 ,
3350
+ U64 = 3 ,
3351
+ };
3352
+
3353
+ /// As of kernel 6.14 there are no defined flags to futex2_waitv.
3354
+ pub const FUTEX2_FLAGS_WAITV = packed struct (u32 ) {
3355
+ _reserved : u32 = 0 ,
3356
+ };
3357
+
3358
+ /// As of kernel 6.14 there are no defined flags to futex2_requeue.
3359
+ pub const FUTEX2_FLAGS_REQUEUE = packed struct (u32 ) {
3360
+ _reserved : u32 = 0 ,
3361
+ };
3362
+
3363
+ /// Flags for futex v2 APIs (futex_wait, futex_wake, futex_requeue, but
3364
+ /// not the futex_waitv syscall, but also used in the futex_waitv struct).
3365
+ pub const FUTEX2_FLAGS = packed struct (u32 ) {
3366
+ size : FUTEX2_SIZE ,
3367
+ numa : bool = false ,
3368
+ _reserved : u4 = 0 ,
3369
+ private : bool ,
3370
+ _undefined : u24 = 0 ,
3371
+ };
3372
+
3351
3373
pub const PROT = struct {
3352
3374
/// page can not be accessed
3353
3375
pub const NONE = 0x0 ;
@@ -8989,17 +9011,16 @@ pub const PTRACE = struct {
8989
9011
pub const GET_SYSCALL_INFO = 0x420e ;
8990
9012
};
8991
9013
8992
- /// A waiter for vectorized wait .
9014
+ /// Futex v2 API, for operating on multiple futexes in one call .
8993
9015
pub const futex_waitv = extern struct {
8994
- // Expected value at uaddr
9016
+ /// Expected value at uaddr, should match size of futex.
8995
9017
val : u64 ,
8996
- /// User address to wait on.
9018
+ /// User address to wait on. Top-bits must be 0 on 32-bit.
8997
9019
uaddr : u64 ,
8998
9020
/// Flags for this waiter.
8999
- flags : u32 ,
9021
+ flags : FUTEX2_FLAGS ,
9000
9022
/// Reserved member to preserve alignment.
9001
- /// Should be 0.
9002
- __reserved : u32 ,
9023
+ __reserved : u32 = 0 ,
9003
9024
};
9004
9025
9005
9026
pub const cache_stat_range = extern struct {
0 commit comments