@@ -673,12 +673,34 @@ pub fn fallocate(fd: i32, mode: i32, offset: i64, length: i64) usize {
673
673
}
674
674
}
675
675
676
- pub fn futex_wait (uaddr : * const i32 , futex_op : u32 , val : i32 , timeout : ? * const timespec ) usize {
677
- return syscall4 (.futex , @intFromPtr (uaddr ), futex_op , @as (u32 , @bitCast (val )), @intFromPtr (timeout ));
676
+ // The 4th parameter to the v1 futex syscall can either be an optional
677
+ // pointer to a timespec, or a uint32, depending on which "op" is being
678
+ // performed.
679
+ pub const futex_param4 = extern union {
680
+ timeout : ? * const timespec ,
681
+ /// On all platforms only the bottom 32-bits of `val2` are relevant.
682
+ /// This is 64-bit to match the pointer in the union.
683
+ val2 : usize ,
684
+ };
685
+
686
+ /// The futex v1 syscall, see also the newer the futex2_{wait,wakeup,requeue,waitv} syscalls.
687
+ ///
688
+ /// The futex_op parameter is a sub-command and flags. The sub-command
689
+ /// defines which of the subsequent paramters are relevant.
690
+ pub fn futex (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 , val2timeout : futex_param4 , uaddr2 : ? * const anyopaque , val3 : u32 ) usize {
691
+ return syscall6 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val , @intFromPtr (val2timeout .timeout ), @intFromPtr (uaddr2 ), val3 );
692
+ }
693
+
694
+ /// Three-argument variation of the v1 futex call. Only suitable for a
695
+ /// futex_op that ignores the remaining arguments (e.g., FUTUX_OP.WAKE).
696
+ pub fn futex_3arg (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 ) usize {
697
+ return syscall3 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val );
678
698
}
679
699
680
- pub fn futex_wake (uaddr : * const i32 , futex_op : u32 , val : i32 ) usize {
681
- return syscall3 (.futex , @intFromPtr (uaddr ), futex_op , @as (u32 , @bitCast (val )));
700
+ /// Four-argument variation on the v1 futex call. Only suitable for
701
+ /// futex_op that ignores the remaining arguments (e.g., FUTEX_OP.WAIT).
702
+ pub fn futex_4arg (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 , timeout : ? * const timespec ) usize {
703
+ return syscall4 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val , @intFromPtr (timeout ));
682
704
}
683
705
684
706
/// Given an array of `futex_waitv`, wait on each uaddr.
@@ -3385,29 +3407,6 @@ pub const FALLOC = struct {
3385
3407
pub const FL_UNSHARE_RANGE = 0x40 ;
3386
3408
};
3387
3409
3388
- pub const FUTEX = struct {
3389
- pub const WAIT = 0 ;
3390
- pub const WAKE = 1 ;
3391
- pub const FD = 2 ;
3392
- pub const REQUEUE = 3 ;
3393
- pub const CMP_REQUEUE = 4 ;
3394
- pub const WAKE_OP = 5 ;
3395
- pub const LOCK_PI = 6 ;
3396
- pub const UNLOCK_PI = 7 ;
3397
- pub const TRYLOCK_PI = 8 ;
3398
- pub const WAIT_BITSET = 9 ;
3399
- pub const WAKE_BITSET = 10 ;
3400
- pub const WAIT_REQUEUE_PI = 11 ;
3401
- pub const CMP_REQUEUE_PI = 12 ;
3402
-
3403
- pub const PRIVATE_FLAG = 128 ;
3404
-
3405
- pub const CLOCK_REALTIME = 256 ;
3406
-
3407
- /// Max numbers of elements in a `futex_waitv` array.
3408
- pub const WAITV_MAX = 128 ;
3409
- };
3410
-
3411
3410
pub const FUTEX2 = struct {
3412
3411
pub const SIZE_U8 = 0x00 ;
3413
3412
pub const SIZE_U16 = 0x01 ;
@@ -3418,6 +3417,69 @@ pub const FUTEX2 = struct {
3418
3417
pub const PRIVATE = FUTEX .PRIVATE_FLAG ;
3419
3418
};
3420
3419
3420
+ // Futex v1 API commands. See futex man page for each command's
3421
+ // interpretation of the futex arguments.
3422
+ pub const FUTEX_COMMAND = enum (u7 ) {
3423
+ WAIT = 0 ,
3424
+ WAKE = 1 ,
3425
+ FD = 2 ,
3426
+ REQUEUE = 3 ,
3427
+ CMP_REQUEUE = 4 ,
3428
+ WAKE_OP = 5 ,
3429
+ LOCK_PI = 6 ,
3430
+ UNLOCK_PI = 7 ,
3431
+ TRYLOCK_PI = 8 ,
3432
+ WAIT_BITSET = 9 ,
3433
+ WAKE_BITSET = 10 ,
3434
+ WAIT_REQUEUE_PI = 11 ,
3435
+ CMP_REQUEUE_PI = 12 ,
3436
+ };
3437
+
3438
+ /// Futex v1 API command and flags for the `futex_op` parameter
3439
+ pub const FUTEX_OP = packed struct (u32 ) {
3440
+ cmd : FUTEX_COMMAND ,
3441
+ private : bool ,
3442
+ realtime : bool = false , // realtime clock vs. monotonic clock
3443
+ _reserved : u23 = 0 ,
3444
+ };
3445
+
3446
+ /// Futex v1 FUTEX_WAKE_OP `val3` operation:
3447
+ pub const FUTEX_WAKE_OP = packed struct (u32 ) {
3448
+ cmd : FUTEX_WAKE_OP_CMD ,
3449
+ /// From C API `FUTEX_OP_ARG_SHIFT`: Use (1 << oparg) as operand
3450
+ arg_shift : bool = false ,
3451
+ cmp : FUTEX_WAKE_OP_CMP ,
3452
+ oparg : u12 ,
3453
+ cmdarg : u12 ,
3454
+ };
3455
+
3456
+ /// Futex v1 cmd for FUTEX_WAKE_OP `val3` command.
3457
+ pub const FUTEX_WAKE_OP_CMD = enum (u3 ) {
3458
+ /// uaddr2 = oparg
3459
+ SET = 0 ,
3460
+ /// uaddr2 += oparg
3461
+ ADD = 1 ,
3462
+ /// uaddr2 |= oparg
3463
+ OR = 2 ,
3464
+ /// uaddr2 &= ~oparg
3465
+ ANDN = 3 ,
3466
+ /// uaddr2 ^= oparg
3467
+ XOR = 4 ,
3468
+ };
3469
+
3470
+ /// Futex v1 comparison op for FUTEX_WAKE_OP `val3` cmp
3471
+ pub const FUTEX_WAKE_OP_CMP = enum (u4 ) {
3472
+ EQ = 0 ,
3473
+ NE = 1 ,
3474
+ LT = 2 ,
3475
+ LE = 3 ,
3476
+ GT = 4 ,
3477
+ GE = 5 ,
3478
+ };
3479
+
3480
+ /// Max numbers of elements in a `futex_waitv` array.
3481
+ pub const FUTEX2_WAITV_MAX = 128 ;
3482
+
3421
3483
pub const PROT = struct {
3422
3484
/// page can not be accessed
3423
3485
pub const NONE = 0x0 ;
0 commit comments