1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Futex2 library addons for futex tests 4 * 5 * Copyright 2021 Collabora Ltd. 6 */ 7 #include <linux/time_types.h> 8 #include <errno.h> 9 #include <stdint.h> 10 #include <stdbool.h> 11 12 #define u64_to_ptr(x) ((void *)(uintptr_t)(x)) 13 14 #ifndef __NR_futex_waitv 15 #define __NR_futex_waitv 449 16 struct futex_waitv { 17 __u64 val; 18 __u64 uaddr; 19 __u32 flags; 20 __u32 __reserved; 21 }; 22 #endif 23 24 #ifndef __NR_futex_wake 25 #define __NR_futex_wake 454 26 #endif 27 28 #ifndef __NR_futex_wait 29 #define __NR_futex_wait 455 30 #endif 31 32 #ifndef FUTEX2_SIZE_U32 33 #define FUTEX2_SIZE_U32 0x02 34 #endif 35 36 #ifndef FUTEX2_NUMA 37 #define FUTEX2_NUMA 0x04 38 #endif 39 40 #ifndef FUTEX2_MPOL 41 #define FUTEX2_MPOL 0x08 42 #endif 43 44 #ifndef FUTEX2_PRIVATE 45 #define FUTEX2_PRIVATE FUTEX_PRIVATE_FLAG 46 #endif 47 48 #ifndef FUTEX2_NO_NODE 49 #define FUTEX_NO_NODE (-1) 50 #endif 51 52 #ifndef FUTEX_32 53 #define FUTEX_32 FUTEX2_SIZE_U32 54 #endif 55 56 struct futex32_numa { 57 futex_t futex; 58 futex_t numa; 59 }; 60 61 /** 62 * futex_waitv - Wait at multiple futexes, wake on any 63 * @waiters: Array of waiters 64 * @nr_waiters: Length of waiters array 65 * @flags: Operation flags 66 * @timo: Optional timeout for operation 67 */ 68 static inline int futex_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters, 69 unsigned long flags, struct timespec *timo, clockid_t clockid) 70 { 71 struct __kernel_timespec ts = { 72 .tv_sec = timo->tv_sec, 73 .tv_nsec = timo->tv_nsec, 74 }; 75 76 return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, &ts, clockid); 77 } 78 79 /* 80 * futex_wait() - block on uaddr with optional timeout 81 * @val: Expected value 82 * @flags: FUTEX2 flags 83 * @timeout: Relative timeout 84 * @clockid: Clock id for the timeout 85 */ 86 static inline int futex2_wait(void *uaddr, long val, unsigned int flags, 87 struct timespec *timeout, clockid_t clockid) 88 { 89 return syscall(__NR_futex_wait, uaddr, val, ~0U, flags, timeout, clockid); 90 } 91 92 /* 93 * futex2_wake() - Wake a number of futexes 94 * @nr: Number of threads to wake at most 95 * @flags: FUTEX2 flags 96 */ 97 static inline int futex2_wake(void *uaddr, int nr, unsigned int flags) 98 { 99 return syscall(__NR_futex_wake, uaddr, ~0U, nr, flags); 100 } 101 102 static inline bool is_futex_waitv_supported(void) 103 { 104 struct timespec ts = {0, 0}; 105 int res = futex_waitv(NULL, 0, 0, &ts, CLOCK_MONOTONIC); 106 107 return !(res < 0 && errno == ENOSYS); 108 } 109