Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | /* SPDX-License-Identifier: GPL-2.0 */ /* * Glibc independent futex library for testing kernel functionality. * Shamelessly stolen from Darren Hart <dvhltc@us.ibm.com> * http://git.kernel.org/cgit/linux/kernel/git/dvhart/futextest.git/ */ #ifndef _FUTEX_H #define _FUTEX_H #include <unistd.h> #include <sys/syscall.h> #include <sys/types.h> #include <linux/futex.h> struct bench_futex_parameters { bool silent; bool fshared; bool mlockall; bool multi; /* lock-pi */ bool pi; /* requeue-pi */ bool broadcast; /* requeue */ unsigned int runtime; /* seconds*/ unsigned int nthreads; unsigned int nfutexes; unsigned int nwakes; unsigned int nrequeue; }; /** * futex_syscall() - SYS_futex syscall wrapper * @uaddr: address of first futex * @op: futex op code * @val: typically expected value of uaddr, but varies by op * @timeout: typically an absolute struct timespec (except where noted * otherwise). Overloaded by some ops * @uaddr2: address of second futex for some ops * @val3: varies by op * @opflags: flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG * * futex_syscall() is used by all the following futex op wrappers. It can also be * used for misuse and abuse testing. Generally, the specific op wrappers * should be used instead. * * These argument descriptions are the defaults for all * like-named arguments in the following wrappers except where noted below. */ static inline int futex_syscall(volatile u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout, volatile u_int32_t *uaddr2, int val3, int opflags) { return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3); } static inline int futex_syscall_nr_requeue(volatile u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue, volatile u_int32_t *uaddr2, int val3, int opflags) { return syscall(SYS_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3); } /** * futex_wait() - block on uaddr with optional timeout * @timeout: relative timeout */ static inline int futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags) { return futex_syscall(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags); } /** * futex_wake() - wake one or more tasks blocked on uaddr * @nr_wake: wake up to this many tasks */ static inline int futex_wake(u_int32_t *uaddr, int nr_wake, int opflags) { return futex_syscall(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags); } /** * futex_lock_pi() - block on uaddr as a PI mutex */ static inline int futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags) { return futex_syscall(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags); } /** * futex_unlock_pi() - release uaddr as a PI mutex, waking the top waiter */ static inline int futex_unlock_pi(u_int32_t *uaddr, int opflags) { return futex_syscall(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags); } /** * futex_cmp_requeue() - requeue tasks from uaddr to uaddr2 * @nr_wake: wake up to this many tasks * @nr_requeue: requeue up to this many tasks */ static inline int futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wake, int nr_requeue, int opflags) { return futex_syscall_nr_requeue(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2, val, opflags); } /** * futex_wait_requeue_pi() - block on uaddr and prepare to requeue to uaddr2 * @uaddr: non-PI futex source * @uaddr2: PI futex target * * This is the first half of the requeue_pi mechanism. It shall always be * paired with futex_cmp_requeue_pi(). */ static inline int futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, struct timespec *timeout, int opflags) { return futex_syscall(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0, opflags); } /** * futex_cmp_requeue_pi() - requeue tasks from uaddr to uaddr2 * @uaddr: non-PI futex source * @uaddr2: PI futex target * @nr_requeue: requeue up to this many tasks * * This is the second half of the requeue_pi mechanism. It shall always be * paired with futex_wait_requeue_pi(). The first waker is always awoken. */ static inline int futex_cmp_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_requeue, int opflags) { return futex_syscall_nr_requeue(uaddr, FUTEX_CMP_REQUEUE_PI, 1, nr_requeue, uaddr2, val, opflags); } #endif /* _FUTEX_H */ |