cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

futextest.h (7449B)


      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
     25typedef 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 */
     77static inline int
     78futex_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 */
     87static inline int
     88futex_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 */
     97static inline int
     98futex_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 */
    109static inline int
    110futex_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 */
    120static inline int
    121futex_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 */
    130static inline int
    131futex_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 */
    139static inline int
    140futex_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 */
    155static inline int
    156futex_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 */
    168static inline int
    169futex_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 */
    184static inline int
    185futex_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 */
    199static inline int
    200futex_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 */
    218static inline u_int32_t
    219futex_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 */
    230static inline u_int32_t
    231futex_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 */
    242static inline u_int32_t
    243futex_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 */
    255static inline u_int32_t
    256futex_set(futex_t *uaddr, u_int32_t newval)
    257{
    258	*uaddr = newval;
    259	return newval;
    260}
    261
    262#endif