root/tools/testing/selftests/futex/include/futextest.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. futex_wait
  2. futex_wake
  3. futex_wait_bitset
  4. futex_wake_bitset
  5. futex_lock_pi
  6. futex_unlock_pi
  7. futex_wake_op
  8. futex_requeue
  9. futex_cmp_requeue
  10. futex_wait_requeue_pi
  11. futex_cmp_requeue_pi
  12. futex_cmpxchg
  13. futex_dec
  14. futex_inc
  15. futex_set

   1 /* SPDX-License-Identifier: GPL-2.0-or-later */
   2 /******************************************************************************
   3  *
   4  *   Copyright © International Business Machines  Corp., 2009
   5  *
   6  * DESCRIPTION
   7  *      Glibc independent futex library for testing kernel functionality.
   8  *
   9  * AUTHOR
  10  *      Darren Hart <dvhart@linux.intel.com>
  11  *
  12  * HISTORY
  13  *      2009-Nov-6: Initial version by Darren Hart <dvhart@linux.intel.com>
  14  *
  15  *****************************************************************************/
  16 
  17 #ifndef _FUTEXTEST_H
  18 #define _FUTEXTEST_H
  19 
  20 #include <unistd.h>
  21 #include <sys/syscall.h>
  22 #include <sys/types.h>
  23 #include <linux/futex.h>
  24 
  25 typedef volatile u_int32_t futex_t;
  26 #define FUTEX_INITIALIZER 0
  27 
  28 /* Define the newer op codes if the system header file is not up to date. */
  29 #ifndef FUTEX_WAIT_BITSET
  30 #define FUTEX_WAIT_BITSET               9
  31 #endif
  32 #ifndef FUTEX_WAKE_BITSET
  33 #define FUTEX_WAKE_BITSET               10
  34 #endif
  35 #ifndef FUTEX_WAIT_REQUEUE_PI
  36 #define FUTEX_WAIT_REQUEUE_PI           11
  37 #endif
  38 #ifndef FUTEX_CMP_REQUEUE_PI
  39 #define FUTEX_CMP_REQUEUE_PI            12
  40 #endif
  41 #ifndef FUTEX_WAIT_REQUEUE_PI_PRIVATE
  42 #define FUTEX_WAIT_REQUEUE_PI_PRIVATE   (FUTEX_WAIT_REQUEUE_PI | \
  43                                          FUTEX_PRIVATE_FLAG)
  44 #endif
  45 #ifndef FUTEX_REQUEUE_PI_PRIVATE
  46 #define FUTEX_CMP_REQUEUE_PI_PRIVATE    (FUTEX_CMP_REQUEUE_PI | \
  47                                          FUTEX_PRIVATE_FLAG)
  48 #endif
  49 
  50 /**
  51  * futex() - SYS_futex syscall wrapper
  52  * @uaddr:      address of first futex
  53  * @op:         futex op code
  54  * @val:        typically expected value of uaddr, but varies by op
  55  * @timeout:    typically an absolute struct timespec (except where noted
  56  *              otherwise). Overloaded by some ops
  57  * @uaddr2:     address of second futex for some ops\
  58  * @val3:       varies by op
  59  * @opflags:    flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
  60  *
  61  * futex() is used by all the following futex op wrappers. It can also be
  62  * used for misuse and abuse testing. Generally, the specific op wrappers
  63  * should be used instead. It is a macro instead of an static inline function as
  64  * some of the types over overloaded (timeout is used for nr_requeue for
  65  * example).
  66  *
  67  * These argument descriptions are the defaults for all
  68  * like-named arguments in the following wrappers except where noted below.
  69  */
  70 #define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
  71         syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
  72 
  73 /**
  74  * futex_wait() - block on uaddr with optional timeout
  75  * @timeout:    relative timeout
  76  */
  77 static inline int
  78 futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
  79 {
  80         return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
  81 }
  82 
  83 /**
  84  * futex_wake() - wake one or more tasks blocked on uaddr
  85  * @nr_wake:    wake up to this many tasks
  86  */
  87 static inline int
  88 futex_wake(futex_t *uaddr, int nr_wake, int opflags)
  89 {
  90         return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
  91 }
  92 
  93 /**
  94  * futex_wait_bitset() - block on uaddr with bitset
  95  * @bitset:     bitset to be used with futex_wake_bitset
  96  */
  97 static inline int
  98 futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout,
  99                   u_int32_t bitset, int opflags)
 100 {
 101         return futex(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
 102                      opflags);
 103 }
 104 
 105 /**
 106  * futex_wake_bitset() - wake one or more tasks blocked on uaddr with bitset
 107  * @bitset:     bitset to compare with that used in futex_wait_bitset
 108  */
 109 static inline int
 110 futex_wake_bitset(futex_t *uaddr, int nr_wake, u_int32_t bitset, int opflags)
 111 {
 112         return futex(uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL, NULL, bitset,
 113                      opflags);
 114 }
 115 
 116 /**
 117  * futex_lock_pi() - block on uaddr as a PI mutex
 118  * @detect:     whether (1) or not (0) to perform deadlock detection
 119  */
 120 static inline int
 121 futex_lock_pi(futex_t *uaddr, struct timespec *timeout, int detect,
 122               int opflags)
 123 {
 124         return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
 125 }
 126 
 127 /**
 128  * futex_unlock_pi() - release uaddr as a PI mutex, waking the top waiter
 129  */
 130 static inline int
 131 futex_unlock_pi(futex_t *uaddr, int opflags)
 132 {
 133         return futex(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags);
 134 }
 135 
 136 /**
 137  * futex_wake_op() - FIXME: COME UP WITH A GOOD ONE LINE DESCRIPTION
 138  */
 139 static inline int
 140 futex_wake_op(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_wake2,
 141               int wake_op, int opflags)
 142 {
 143         return futex(uaddr, FUTEX_WAKE_OP, nr_wake, nr_wake2, uaddr2, wake_op,
 144                      opflags);
 145 }
 146 
 147 /**
 148  * futex_requeue() - requeue without expected value comparison, deprecated
 149  * @nr_wake:    wake up to this many tasks
 150  * @nr_requeue: requeue up to this many tasks
 151  *
 152  * Due to its inherently racy implementation, futex_requeue() is deprecated in
 153  * favor of futex_cmp_requeue().
 154  */
 155 static inline int
 156 futex_requeue(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_requeue,
 157               int opflags)
 158 {
 159         return futex(uaddr, FUTEX_REQUEUE, nr_wake, nr_requeue, uaddr2, 0,
 160                      opflags);
 161 }
 162 
 163 /**
 164  * futex_cmp_requeue() - requeue tasks from uaddr to uaddr2
 165  * @nr_wake:    wake up to this many tasks
 166  * @nr_requeue: requeue up to this many tasks
 167  */
 168 static inline int
 169 futex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
 170                   int nr_requeue, int opflags)
 171 {
 172         return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
 173                      val, opflags);
 174 }
 175 
 176 /**
 177  * futex_wait_requeue_pi() - block on uaddr and prepare to requeue to uaddr2
 178  * @uaddr:      non-PI futex source
 179  * @uaddr2:     PI futex target
 180  *
 181  * This is the first half of the requeue_pi mechanism. It shall always be
 182  * paired with futex_cmp_requeue_pi().
 183  */
 184 static inline int
 185 futex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2,
 186                       struct timespec *timeout, int opflags)
 187 {
 188         return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
 189                      opflags);
 190 }
 191 
 192 /**
 193  * futex_cmp_requeue_pi() - requeue tasks from uaddr to uaddr2 (PI aware)
 194  * @uaddr:      non-PI futex source
 195  * @uaddr2:     PI futex target
 196  * @nr_wake:    wake up to this many tasks
 197  * @nr_requeue: requeue up to this many tasks
 198  */
 199 static inline int
 200 futex_cmp_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
 201                      int nr_requeue, int opflags)
 202 {
 203         return futex(uaddr, FUTEX_CMP_REQUEUE_PI, nr_wake, nr_requeue, uaddr2,
 204                      val, opflags);
 205 }
 206 
 207 /**
 208  * futex_cmpxchg() - atomic compare and exchange
 209  * @uaddr:      The address of the futex to be modified
 210  * @oldval:     The expected value of the futex
 211  * @newval:     The new value to try and assign the futex
 212  *
 213  * Implement cmpxchg using gcc atomic builtins.
 214  * http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
 215  *
 216  * Return the old futex value.
 217  */
 218 static inline u_int32_t
 219 futex_cmpxchg(futex_t *uaddr, u_int32_t oldval, u_int32_t newval)
 220 {
 221         return __sync_val_compare_and_swap(uaddr, oldval, newval);
 222 }
 223 
 224 /**
 225  * futex_dec() - atomic decrement of the futex value
 226  * @uaddr:      The address of the futex to be modified
 227  *
 228  * Return the new futex value.
 229  */
 230 static inline u_int32_t
 231 futex_dec(futex_t *uaddr)
 232 {
 233         return __sync_sub_and_fetch(uaddr, 1);
 234 }
 235 
 236 /**
 237  * futex_inc() - atomic increment of the futex value
 238  * @uaddr:      the address of the futex to be modified
 239  *
 240  * Return the new futex value.
 241  */
 242 static inline u_int32_t
 243 futex_inc(futex_t *uaddr)
 244 {
 245         return __sync_add_and_fetch(uaddr, 1);
 246 }
 247 
 248 /**
 249  * futex_set() - atomic decrement of the futex value
 250  * @uaddr:      the address of the futex to be modified
 251  * @newval:     New value for the atomic_t
 252  *
 253  * Return the new futex value.
 254  */
 255 static inline u_int32_t
 256 futex_set(futex_t *uaddr, u_int32_t newval)
 257 {
 258         *uaddr = newval;
 259         return newval;
 260 }
 261 
 262 #endif

/* [<][>][^][v][top][bottom][index][help] */