^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Glibc independent futex library for testing kernel functionality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Shamelessly stolen from Darren Hart <dvhltc@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * http://git.kernel.org/cgit/linux/kernel/git/dvhart/futextest.git/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #ifndef _FUTEX_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define _FUTEX_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sys/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/futex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * futex() - SYS_futex syscall wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * @uaddr: address of first futex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * @op: futex op code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * @val: typically expected value of uaddr, but varies by op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * @timeout: typically an absolute struct timespec (except where noted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * otherwise). Overloaded by some ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * @uaddr2: address of second futex for some ops\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * @val3: varies by op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * @opflags: flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * futex() is used by all the following futex op wrappers. It can also be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * used for misuse and abuse testing. Generally, the specific op wrappers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * should be used instead. It is a macro instead of an static inline function as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * some of the types over overloaded (timeout is used for nr_requeue for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * example).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * These argument descriptions are the defaults for all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * like-named arguments in the following wrappers except where noted below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * futex_wait() - block on uaddr with optional timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @timeout: relative timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * futex_wake() - wake one or more tasks blocked on uaddr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * @nr_wake: wake up to this many tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * futex_lock_pi() - block on uaddr as a PI mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * futex_unlock_pi() - release uaddr as a PI mutex, waking the top waiter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) futex_unlock_pi(u_int32_t *uaddr, int opflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return futex(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * futex_cmp_requeue() - requeue tasks from uaddr to uaddr2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @nr_wake: wake up to this many tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * @nr_requeue: requeue up to this many tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wake,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int nr_requeue, int opflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) val, opflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #endif /* _FUTEX_H */