@@ -703,58 +703,57 @@ pub fn futex_4arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, timeout
703
703
return syscall4 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val , @intFromPtr (timeout ));
704
704
}
705
705
706
- /// Given an array of `futex_waitv `, wait on each uaddr.
706
+ /// Given an array of `futex2_waitone `, wait on each uaddr.
707
707
/// The thread wakes if a futex_wake() is performed at any uaddr.
708
- /// The syscall returns immediately if any waiter has *uaddr != val.
709
- /// timeout is an optional timeout value for the operation.
710
- /// Each waiter has individual flags.
711
- /// The `flags` argument for the syscall should be used solely for specifying
712
- /// the timeout as realtime, if needed.
713
- /// Flags for private futexes, sizes, etc. should be used on the
714
- /// individual flags of each waiter.
708
+ /// The syscall returns immediately if any futex has *uaddr != val.
709
+ /// timeout is an optional, absolute timeout value for the operation.
710
+ /// The `flags` argument is for future use and currently should be `.{}`.
711
+ /// Flags for private futexes, sizes, etc. should be set on the
712
+ /// individual flags of each `futex2_waitone`.
715
713
///
716
714
/// Returns the array index of one of the woken futexes.
717
715
/// No further information is provided: any number of other futexes may also
718
716
/// have been woken by the same event, and if more than one futex was woken,
719
717
/// the returned index may refer to any one of them.
720
718
/// (It is not necessaryily the futex with the smallest index, nor the one
721
719
/// most recently woken, nor...)
720
+ ///
721
+ /// Requires at least kernel v5.16.
722
722
pub fn futex2_waitv (
723
- /// List of futexes to wait on.
724
- waiters : [* ]futex_waitv ,
725
- /// Length of `waiters`.
723
+ futexes : [* ]const futex2_waitone ,
724
+ /// Length of `futexes`. Max of FUTEX2_WAITONE_MAX.
726
725
nr_futexes : u32 ,
727
- /// Flag for timeout (monotonic/realtime).
728
- flags : u32 ,
729
- /// Optional absolute timeout.
730
- timeout : ? * const timespec ,
726
+ flags : FUTEX2_FLAGS_WAITV ,
727
+ /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms.
728
+ timeout : ? * const kernel_timespec ,
731
729
/// Clock to be used for the timeout, realtime or monotonic.
732
730
clockid : clockid_t ,
733
731
) usize {
734
732
return syscall5 (
735
733
.futex_waitv ,
736
- @intFromPtr (waiters ),
734
+ @intFromPtr (futexes ),
737
735
nr_futexes ,
738
- flags ,
736
+ @as ( u32 , @bitCast ( flags )) ,
739
737
@intFromPtr (timeout ),
740
- @bitCast ( @as ( isize , @ intFromEnum (clockid )) ),
738
+ @intFromEnum (clockid ),
741
739
);
742
740
}
743
741
744
- /// Wait on a futex.
745
- /// Identical to the traditional `FUTEX.FUTEX_WAIT_BITSET` op, except it is part of the
746
- /// futex2 familiy of calls.
742
+ /// Wait on a single futex.
743
+ /// Identical to the futex v1 `FUTEX.FUTEX_WAIT_BITSET` op, except it is part of the
744
+ /// futex2 family of calls.
745
+ ///
746
+ /// Requires at least kernel v6.7.
747
747
pub fn futex2_wait (
748
748
/// Address of the futex to wait on.
749
749
uaddr : * const anyopaque ,
750
750
/// Value of `uaddr`.
751
751
val : usize ,
752
- /// Bitmask.
752
+ /// Bitmask to match against incoming wakeup masks. Must not be zero .
753
753
mask : usize ,
754
- /// `FUTEX2` flags.
755
- flags : u32 ,
756
- /// Optional absolute timeout.
757
- timeout : ? * const timespec ,
754
+ flags : FUTEX2_FLAGS ,
755
+ /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms.
756
+ timeout : ? * const kernel_timespec ,
758
757
/// Clock to be used for the timeout, realtime or monotonic.
759
758
clockid : clockid_t ,
760
759
) usize {
@@ -763,52 +762,55 @@ pub fn futex2_wait(
763
762
@intFromPtr (uaddr ),
764
763
val ,
765
764
mask ,
766
- flags ,
765
+ @as ( u32 , @bitCast ( flags )) ,
767
766
@intFromPtr (timeout ),
768
- @bitCast ( @as ( isize , @ intFromEnum (clockid )) ),
767
+ @intFromEnum (clockid ),
769
768
);
770
769
}
771
770
772
- /// Wake a number of futexes .
773
- /// Identical to the traditional `FUTEX.FUTEX_WAIT_BITSET ` op, except it is part of the
771
+ /// Wake (subset of) waiters on given futex .
772
+ /// Identical to the traditional `FUTEX.FUTEX_WAKE_BITSET ` op, except it is part of the
774
773
/// futex2 family of calls.
774
+ ///
775
+ /// Requires at least kernel v6.7.
775
776
pub fn futex2_wake (
776
- /// Address of the futex(es) to wake.
777
+ /// Futex to wake
777
778
uaddr : * const anyopaque ,
778
- /// Bitmask
779
+ /// Bitmask to match against waiters.
779
780
mask : usize ,
780
- /// Number of the futexes to wake.
781
- nr : i32 ,
782
- /// `FUTEX2` flags.
783
- flags : u32 ,
781
+ /// Maximum number of waiters on the futex to wake.
782
+ nr_wake : i32 ,
783
+ flags : FUTEX2_FLAGS ,
784
784
) usize {
785
785
return syscall4 (
786
786
.futex_wake ,
787
787
@intFromPtr (uaddr ),
788
788
mask ,
789
- @bitCast ( @ as (isize , nr )),
790
- flags ,
789
+ @as (u32 , @bitCast ( nr_wake )),
790
+ @as ( u32 , @bitCast ( flags )) ,
791
791
);
792
792
}
793
793
794
- /// Requeue a waiter from one futex to another.
794
+ /// Wake and/or requeue waiter(s) from one futex to another.
795
795
/// Identical to `FUTEX.CMP_REQUEUE`, except it is part of the futex2 family of calls.
796
+ ///
797
+ /// Requires at least kernel v6.7.
796
798
pub fn futex2_requeue (
797
- /// Array describing the source and destination futex .
798
- waiters : [* ]futex_waitv ,
799
- /// Unused .
800
- flags : u32 ,
801
- /// Number of futexes to wake.
799
+ /// The source and destination futexes. Must be a 2-element array .
800
+ waiters : [* ]const futex2_waitone ,
801
+ /// Currently unused .
802
+ flags : FUTEX2_FLAGS_REQUEUE ,
803
+ /// Maximum number of waiters to wake on the source futex .
802
804
nr_wake : i32 ,
803
- /// Number of futexes to requeue .
805
+ /// Maximum number of waiters to transfer to the destination futex .
804
806
nr_requeue : i32 ,
805
807
) usize {
806
808
return syscall4 (
807
809
.futex_requeue ,
808
810
@intFromPtr (waiters ),
809
- flags ,
810
- @bitCast ( @ as (isize , nr_wake )),
811
- @bitCast ( @ as (isize , nr_requeue )),
811
+ @as ( u32 , @bitCast ( flags )) ,
812
+ @as (u32 , @bitCast ( nr_wake )),
813
+ @as (u32 , @bitCast ( nr_requeue )),
812
814
);
813
815
}
814
816
@@ -3407,16 +3409,6 @@ pub const FALLOC = struct {
3407
3409
pub const FL_UNSHARE_RANGE = 0x40 ;
3408
3410
};
3409
3411
3410
- pub const FUTEX2 = struct {
3411
- pub const SIZE_U8 = 0x00 ;
3412
- pub const SIZE_U16 = 0x01 ;
3413
- pub const SIZE_U32 = 0x02 ;
3414
- pub const SIZE_U64 = 0x03 ;
3415
- pub const NUMA = 0x04 ;
3416
-
3417
- pub const PRIVATE = FUTEX .PRIVATE_FLAG ;
3418
- };
3419
-
3420
3412
// Futex v1 API commands. See futex man page for each command's
3421
3413
// interpretation of the futex arguments.
3422
3414
pub const FUTEX_COMMAND = enum (u7 ) {
@@ -3477,8 +3469,38 @@ pub const FUTEX_WAKE_OP_CMP = enum(u4) {
3477
3469
GE = 5 ,
3478
3470
};
3479
3471
3480
- /// Max numbers of elements in a `futex_waitv` array.
3481
- pub const FUTEX2_WAITV_MAX = 128 ;
3472
+ /// Max numbers of elements in a `futex2_waitone` array.
3473
+ pub const FUTEX2_WAITONE_MAX = 128 ;
3474
+
3475
+ /// For futex v2 API, the size of the futex at the uaddr. v1 futex are
3476
+ /// always implicitly U32. As of kernel v6.14, only U32 is implemented
3477
+ /// for v2 futexes.
3478
+ pub const FUTEX2_SIZE = enum (u2 ) {
3479
+ U8 = 0 ,
3480
+ U16 = 1 ,
3481
+ U32 = 2 ,
3482
+ U64 = 3 ,
3483
+ };
3484
+
3485
+ /// As of kernel 6.14 there are no defined flags to futex2_waitv.
3486
+ pub const FUTEX2_FLAGS_WAITV = packed struct (u32 ) {
3487
+ _reserved : u32 = 0 ,
3488
+ };
3489
+
3490
+ /// As of kernel 6.14 there are no defined flags to futex2_requeue.
3491
+ pub const FUTEX2_FLAGS_REQUEUE = packed struct (u32 ) {
3492
+ _reserved : u32 = 0 ,
3493
+ };
3494
+
3495
+ /// Flags for futex v2 APIs (futex2_wait, futex2_wake, futex2_requeue, but
3496
+ /// not the futex2_waitv syscall, but also used in the futex2_waitone struct).
3497
+ pub const FUTEX2_FLAGS = packed struct (u32 ) {
3498
+ size : FUTEX2_SIZE ,
3499
+ numa : bool = false ,
3500
+ _reserved : u4 = 0 ,
3501
+ private : bool ,
3502
+ _undefined : u24 = 0 ,
3503
+ };
3482
3504
3483
3505
pub const PROT = struct {
3484
3506
/// page can not be accessed
@@ -9343,17 +9365,17 @@ pub const PTRACE = struct {
9343
9365
pub const GET_SYSCALL_INFO = 0x420e ;
9344
9366
};
9345
9367
9346
- /// A waiter for vectorized wait.
9347
- pub const futex_waitv = extern struct {
9348
- // Expected value at uaddr
9368
+ /// For futex2_waitv and futex2_requeue. Arrays of `futex2_waitone` allow
9369
+ /// waiting on multiple futexes in one call.
9370
+ pub const futex2_waitone = extern struct {
9371
+ /// Expected value at uaddr, should match size of futex.
9349
9372
val : u64 ,
9350
- /// User address to wait on.
9373
+ /// User address to wait on. Top-bits must be 0 on 32-bit.
9351
9374
uaddr : u64 ,
9352
9375
/// Flags for this waiter.
9353
- flags : u32 ,
9376
+ flags : FUTEX2_FLAGS ,
9354
9377
/// Reserved member to preserve alignment.
9355
- /// Should be 0.
9356
- __reserved : u32 ,
9378
+ __reserved : u32 = 0 ,
9357
9379
};
9358
9380
9359
9381
pub const cache_stat_range = extern struct {
0 commit comments