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