| ... | ... | @@ -703,15 +703,13 @@ 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 |
| ... | ... | @@ -719,42 +717,43 @@ pub fn futex_4arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, timeout |
| 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 { |