@@ -647,12 +647,34 @@ pub fn fallocate(fd: i32, mode: i32, offset: i64, length: i64) usize {
647
647
}
648
648
}
649
649
650
- pub fn futex_wait (uaddr : * const i32 , futex_op : u32 , val : i32 , timeout : ? * const timespec ) usize {
651
- return syscall4 (.futex , @intFromPtr (uaddr ), futex_op , @as (u32 , @bitCast (val )), @intFromPtr (timeout ));
650
+ // The 4th parameter to the v1 futex syscall can either be an optional
651
+ // pointer to a timespec, or a uint32, depending on which "op" is being
652
+ // performed.
653
+ pub const futex_param4 = extern union {
654
+ timeout : ? * const timespec ,
655
+ /// On all platforms only the bottom 32-bits of `val2` are relevant.
656
+ /// This is 64-bit to match the pointer in the union.
657
+ val2 : usize ,
658
+ };
659
+
660
+ /// The futex v1 syscall, see also the newer the futex2_{wait,wakeup,requeue,waitv} syscalls.
661
+ ///
662
+ /// The futex_op parameter is a sub-command and flags. The sub-command
663
+ /// defines which of the subsequent paramters are relevant.
664
+ pub fn futex (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 , val2timeout : futex_param4 , uaddr2 : ? * const anyopaque , val3 : u32 ) usize {
665
+ return syscall6 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val , @intFromPtr (val2timeout .timeout ), @intFromPtr (uaddr2 ), val3 );
666
+ }
667
+
668
+ /// Three-argument variation of the v1 futex call. Only suitable for a
669
+ /// futex_op that ignores the remaining arguments (e.g., FUTUX_OP.WAKE).
670
+ pub fn futex_3arg (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 ) usize {
671
+ return syscall3 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val );
652
672
}
653
673
654
- pub fn futex_wake (uaddr : * const i32 , futex_op : u32 , val : i32 ) usize {
655
- return syscall3 (.futex , @intFromPtr (uaddr ), futex_op , @as (u32 , @bitCast (val )));
674
+ /// Four-argument variation on the v1 futex call. Only suitable for
675
+ /// futex_op that ignores the remaining arguments (e.g., FUTEX_OP.WAIT).
676
+ pub fn futex_4arg (uaddr : * const anyopaque , futex_op : FUTEX_OP , val : u32 , timeout : ? * const timespec ) usize {
677
+ return syscall4 (.futex , @intFromPtr (uaddr ), @as (u32 , @bitCast (futex_op )), val , @intFromPtr (timeout ));
656
678
}
657
679
658
680
/// Given an array of `futex_waitv`, wait on each uaddr.
@@ -3253,29 +3275,6 @@ pub const FALLOC = struct {
3253
3275
pub const FL_UNSHARE_RANGE = 0x40 ;
3254
3276
};
3255
3277
3256
- pub const FUTEX = struct {
3257
- pub const WAIT = 0 ;
3258
- pub const WAKE = 1 ;
3259
- pub const FD = 2 ;
3260
- pub const REQUEUE = 3 ;
3261
- pub const CMP_REQUEUE = 4 ;
3262
- pub const WAKE_OP = 5 ;
3263
- pub const LOCK_PI = 6 ;
3264
- pub const UNLOCK_PI = 7 ;
3265
- pub const TRYLOCK_PI = 8 ;
3266
- pub const WAIT_BITSET = 9 ;
3267
- pub const WAKE_BITSET = 10 ;
3268
- pub const WAIT_REQUEUE_PI = 11 ;
3269
- pub const CMP_REQUEUE_PI = 12 ;
3270
-
3271
- pub const PRIVATE_FLAG = 128 ;
3272
-
3273
- pub const CLOCK_REALTIME = 256 ;
3274
-
3275
- /// Max numbers of elements in a `futex_waitv` array.
3276
- pub const WAITV_MAX = 128 ;
3277
- };
3278
-
3279
3278
pub const FUTEX2 = struct {
3280
3279
pub const SIZE_U8 = 0x00 ;
3281
3280
pub const SIZE_U16 = 0x01 ;
@@ -3286,6 +3285,69 @@ pub const FUTEX2 = struct {
3286
3285
pub const PRIVATE = FUTEX .PRIVATE_FLAG ;
3287
3286
};
3288
3287
3288
+ // Futex v1 API commands. See futex man page for each command's
3289
+ // interpretation of the futex arguments.
3290
+ pub const FUTEX_COMMAND = enum (u7 ) {
3291
+ WAIT = 0 ,
3292
+ WAKE = 1 ,
3293
+ FD = 2 ,
3294
+ REQUEUE = 3 ,
3295
+ CMP_REQUEUE = 4 ,
3296
+ WAKE_OP = 5 ,
3297
+ LOCK_PI = 6 ,
3298
+ UNLOCK_PI = 7 ,
3299
+ TRYLOCK_PI = 8 ,
3300
+ WAIT_BITSET = 9 ,
3301
+ WAKE_BITSET = 10 ,
3302
+ WAIT_REQUEUE_PI = 11 ,
3303
+ CMP_REQUEUE_PI = 12 ,
3304
+ };
3305
+
3306
+ /// Futex v1 API command and flags for the `futex_op` parameter
3307
+ pub const FUTEX_OP = packed struct (u32 ) {
3308
+ cmd : FUTEX_COMMAND ,
3309
+ private : bool ,
3310
+ realtime : bool = false , // realtime clock vs. monotonic clock
3311
+ _reserved : u23 = 0 ,
3312
+ };
3313
+
3314
+ /// Futex v1 FUTEX_WAKE_OP `val3` operation:
3315
+ pub const FUTEX_WAKE_OP = packed struct (u32 ) {
3316
+ cmd : FUTEX_WAKE_OP_CMD ,
3317
+ /// From C API `FUTEX_OP_ARG_SHIFT`: Use (1 << oparg) as operand
3318
+ arg_shift : bool = false ,
3319
+ cmp : FUTEX_WAKE_OP_CMP ,
3320
+ oparg : u12 ,
3321
+ cmdarg : u12 ,
3322
+ };
3323
+
3324
+ /// Futex v1 cmd for FUTEX_WAKE_OP `val3` command.
3325
+ pub const FUTEX_WAKE_OP_CMD = enum (u3 ) {
3326
+ /// uaddr2 = oparg
3327
+ SET = 0 ,
3328
+ /// uaddr2 += oparg
3329
+ ADD = 1 ,
3330
+ /// uaddr2 |= oparg
3331
+ OR = 2 ,
3332
+ /// uaddr2 &= ~oparg
3333
+ ANDN = 3 ,
3334
+ /// uaddr2 ^= oparg
3335
+ XOR = 4 ,
3336
+ };
3337
+
3338
+ /// Futex v1 comparison op for FUTEX_WAKE_OP `val3` cmp
3339
+ pub const FUTEX_WAKE_OP_CMP = enum (u4 ) {
3340
+ EQ = 0 ,
3341
+ NE = 1 ,
3342
+ LT = 2 ,
3343
+ LE = 3 ,
3344
+ GT = 4 ,
3345
+ GE = 5 ,
3346
+ };
3347
+
3348
+ /// Max numbers of elements in a `futex_waitv` array.
3349
+ pub const FUTEX2_WAITV_MAX = 128 ;
3350
+
3289
3351
pub const PROT = struct {
3290
3352
/// page can not be accessed
3291
3353
pub const NONE = 0x0 ;
0 commit comments