16270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/******************************************************************************
26270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
36270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   Copyright © International Business Machines  Corp., 2009
4b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis *   Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
56270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
66270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   This program is free software;  you can redistribute it and/or modify
76270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   it under the terms of the GNU General Public License as published by
86270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   the Free Software Foundation; either version 2 of the License, or
96270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   (at your option) any later version.
106270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
116270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   This program is distributed in the hope that it will be useful,
126270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
136270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
146270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   the GNU General Public License for more details.
156270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
166270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   You should have received a copy of the GNU General Public License
176270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   along with this program;  if not, write to the Free Software
186270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
196270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
206270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * NAME
216270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *      futextest.h
226270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
236270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * DESCRIPTION
246270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *      Glibc independent futex library for testing kernel functionality.
256270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
266270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * AUTHOR
276270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *      Darren Hart <dvhltc@us.ibm.com>
286270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
296270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * HISTORY
306270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *      2009-Nov-6: Initial version by Darren Hart <dvhltc@us.ibm.com>
316270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
326270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *****************************************************************************/
336270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
346270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef _FUTEXTEST_H
356270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#define _FUTEXTEST_H
366270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
376270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#include <unistd.h>
386270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#include <sys/syscall.h>
396270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#include <sys/types.h>
406270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#include <linux/futex.h>
415571228702e60a99e547d7b66b7182ab9bd848e4Stanislav Kholmanskikh#include "lapi/futex.h"
426270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
436270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#define FUTEX_INITIALIZER 0
446270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
45b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#ifndef FUTEX_CMP_REQUEUE
46b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_CMP_REQUEUE	4
47b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#endif
48b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#ifndef FUTEX_WAKE_OP
49b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_WAKE_OP		5
50b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#endif
51b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#ifndef FUTEX_LOCK_PI
52b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_LOCK_PI		6
53b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#endif
54b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#ifndef FUTEX_UNLOCK_PI
55b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_UNLOCK_PI	7
56b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#endif
576270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef FUTEX_WAIT_BITSET
58b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_WAIT_BITSET	9
596270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
606270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef FUTEX_WAKE_BITSET
61b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_WAKE_BITSET	10
626270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
636270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef FUTEX_WAIT_REQUEUE_PI
64b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_WAIT_REQUEUE_PI	11
656270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
666270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef FUTEX_CMP_REQUEUE_PI
67b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_CMP_REQUEUE_PI	12
68b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#endif
69b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis#ifndef FUTEX_PRIVATE_FLAG
70b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_PRIVATE_FLAG	128
716270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
726270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef FUTEX_WAIT_REQUEUE_PI_PRIVATE
73b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_WAIT_REQUEUE_PI_PRIVATE	(FUTEX_WAIT_REQUEUE_PI | \
746270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis					 FUTEX_PRIVATE_FLAG)
756270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
766270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#ifndef FUTEX_REQUEUE_PI_PRIVATE
77b7886ad2eb27877256433380553208e597778bc5Cyril Hrubis# define FUTEX_CMP_REQUEUE_PI_PRIVATE	(FUTEX_CMP_REQUEUE_PI | \
786270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis					 FUTEX_PRIVATE_FLAG)
796270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
806270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
815f4378da2dddfbd51a80648e2ab70bd86b30da9eCyril Hrubis#ifndef FUTEX_CLOCK_REALTIME
825f4378da2dddfbd51a80648e2ab70bd86b30da9eCyril Hrubis# define FUTEX_CLOCK_REALTIME 256
835f4378da2dddfbd51a80648e2ab70bd86b30da9eCyril Hrubis#endif
845f4378da2dddfbd51a80648e2ab70bd86b30da9eCyril Hrubis
856270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
866270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex() - SYS_futex syscall wrapper
876270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	address of first futex
886270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @op:		futex op code
896270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @val:	typically expected value of uaddr, but varies by op
906270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @timeout:	typically an absolute struct timespec (except where noted
916270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *		otherwise). Overloaded by some ops
926270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr2:	address of second futex for some ops\
936270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @val3:	varies by op
946270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @opflags:	flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
956270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
966270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex() is used by all the following futex op wrappers. It can also be
976270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * used for misuse and abuse testing. Generally, the specific op wrappers
986270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * should be used instead. It is a macro instead of an static inline function as
996270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * some of the types over overloaded (timeout is used for nr_requeue for
1006270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * example).
1016270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
1026270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * These argument descriptions are the defaults for all
1036270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * like-named arguments in the following wrappers except where noted below.
1046270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1056270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
1066270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
1076270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1086270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1096270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_wait() - block on uaddr with optional timeout
1106270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @timeout:	relative timeout
1116270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1126270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1136270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
1146270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1156270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
1166270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1176270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1186270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1196270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_wake() - wake one or more tasks blocked on uaddr
1206270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_wake:	wake up to this many tasks
1216270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1226270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1236270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_wake(futex_t *uaddr, int nr_wake, int opflags)
1246270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1256270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
1266270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1276270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1286270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1296270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_wait_bitset() - block on uaddr with bitset
1306270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @bitset:	bitset to be used with futex_wake_bitset
1316270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1326270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1336270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout,
1346270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		  u_int32_t bitset, int opflags)
1356270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1366270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
1376270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     opflags);
1386270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1396270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1406270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1416270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_wake_bitset() - wake one or more tasks blocked on uaddr with bitset
1426270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @bitset:	bitset to compare with that used in futex_wait_bitset
1436270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1446270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1456270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_wake_bitset(futex_t *uaddr, int nr_wake, u_int32_t bitset, int opflags)
1466270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1476270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL, NULL, bitset,
1486270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     opflags);
1496270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1506270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1516270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1526270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_lock_pi() - block on uaddr as a PI mutex
1536270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @detect:	whether (1) or not (0) to perform deadlock detection
1546270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1556270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1566270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_lock_pi(futex_t *uaddr, struct timespec *timeout, int detect,
1576270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	      int opflags)
1586270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1596270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
1606270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1616270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1626270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1636270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_unlock_pi() - release uaddr as a PI mutex, waking the top waiter
1646270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1656270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1666270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_unlock_pi(futex_t *uaddr, int opflags)
1676270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1686270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags);
1696270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1706270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1716270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1726270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_wake_op() - FIXME: COME UP WITH A GOOD ONE LINE DESCRIPTION
1736270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1746270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1756270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_wake_op(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_wake2,
1766270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	      int wake_op, int opflags)
1776270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1786270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_WAKE_OP, nr_wake, nr_wake2, uaddr2, wake_op,
1796270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     opflags);
1806270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1816270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1826270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1836270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_requeue() - requeue without expected value comparison, deprecated
1846270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_wake:	wake up to this many tasks
1856270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_requeue:	requeue up to this many tasks
1866270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
1876270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * Due to its inherently racy implementation, futex_requeue() is deprecated in
1886270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * favor of futex_cmp_requeue().
1896270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
1906270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
1916270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_requeue(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_requeue,
1926270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	      int opflags)
1936270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
1946270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_REQUEUE, nr_wake, nr_requeue, uaddr2, 0,
1956270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     opflags);
1966270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
1976270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
1986270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
1996270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_cmp_requeue() - requeue tasks from uaddr to uaddr2
2006270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_wake:	wake up to this many tasks
2016270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_requeue:	requeue up to this many tasks
2026270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2036270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
2046270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
2056270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		  int nr_requeue, int opflags)
2066270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2076270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
2086270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     val, opflags);
2096270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2106270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2116270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
2126270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_wait_requeue_pi() - block on uaddr and prepare to requeue to uaddr2
2136270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	non-PI futex source
2146270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr2:	PI futex target
2156270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
2166270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * This is the first half of the requeue_pi mechanism. It shall always be
2176270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * paired with futex_cmp_requeue_pi().
2186270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2196270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
2206270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2,
2216270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		      struct timespec *timeout, int opflags)
2226270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2236270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
2246270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     opflags);
2256270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2266270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2276270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
2286270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_cmp_requeue_pi() - requeue tasks from uaddr to uaddr2 (PI aware)
2296270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	non-PI futex source
2306270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr2:	PI futex target
2316270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_wake:	wake up to this many tasks
2326270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @nr_requeue:	requeue up to this many tasks
2336270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2346270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline int
2356270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_cmp_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
2366270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     int nr_requeue, int opflags)
2376270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2386270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return futex(uaddr, FUTEX_CMP_REQUEUE_PI, nr_wake, nr_requeue, uaddr2, val,
2396270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis		     opflags);
2406270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2416270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2426270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
2436270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_cmpxchg() - atomic compare and exchange
2446270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	The address of the futex to be modified
2456270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @oldval:	The expected value of the futex
2466270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @newval:	The new value to try and assign the futex
2476270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
2486270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * Implement cmpxchg using gcc atomic builtins.
2496270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
2506270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
2516270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * Return the old futex value.
2526270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2536270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline u_int32_t
2546270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_cmpxchg(futex_t *uaddr, u_int32_t oldval, u_int32_t newval)
2556270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2566270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return __sync_val_compare_and_swap(uaddr, oldval, newval);
2576270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2586270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2596270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
2606270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_dec() - atomic decrement of the futex value
2616270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	The address of the futex to be modified
2626270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
2636270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * Return the new futex value.
2646270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2656270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline u_int32_t
2666270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_dec(futex_t *uaddr)
2676270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2686270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return __sync_sub_and_fetch(uaddr, 1);
2696270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2706270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2716270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
2726270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_inc() - atomic increment of the futex value
2736270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	the address of the futex to be modified
2746270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
2756270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * Return the new futex value.
2766270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2776270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline u_int32_t
2786270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_inc(futex_t *uaddr)
2796270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2806270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return __sync_add_and_fetch(uaddr, 1);
2816270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2826270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2836270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis/**
2846270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * futex_set() - atomic decrement of the futex value
2856270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @uaddr:	the address of the futex to be modified
2866270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * @newval:	New value for the atomic_t
2876270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis *
2886270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis * Return the new futex value.
2896270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis */
2906270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisstatic inline u_int32_t
2916270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubisfutex_set(futex_t *uaddr, u_int32_t newval)
2926270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis{
2936270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	*uaddr = newval;
2946270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis	return newval;
2956270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis}
2966270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis
2976270ba2ebe999ffdb1364e5e814d7e56070a0198Cyril Hrubis#endif
298