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