(root)/
strace-6.5/
tests/
futex.c
       1  /*
       2   * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
       3   * Copyright (c) 2016-2023 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: GPL-2.0-or-later
       7   */
       8  
       9  #include "tests.h"
      10  
      11  #include "scno.h"
      12  
      13  #ifdef __NR_futex
      14  
      15  # include <errno.h>
      16  # include <stdarg.h>
      17  # include <stdio.h>
      18  # include <stdint.h>
      19  # include <unistd.h>
      20  
      21  # include <sys/time.h>
      22  
      23  # ifndef FUTEX_PRIVATE_FLAG
      24  #  define FUTEX_PRIVATE_FLAG 128
      25  # endif
      26  # ifndef FUTEX_CLOCK_REALTIME
      27  #  define FUTEX_CLOCK_REALTIME 256
      28  # endif
      29  # ifndef FUTEX_CMD_MASK
      30  #  define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
      31  # endif
      32  
      33  # include "xlat.h"
      34  # include "xlat/futexops.h"
      35  # include "xlat/futexwakeops.h"
      36  # include "xlat/futexwakecmps.h"
      37  
      38  static void
      39  futex_error(int *uaddr, int op, unsigned long val, unsigned long timeout,
      40  	    int *uaddr2, unsigned long val3, int rc, const char *func, int line)
      41  {
      42  	perror_msg_and_fail("%s:%d: futex(%p, %#x, %#x, %#lx, %p, %#x) = %d",
      43  		func, line, uaddr, op, (unsigned) val, timeout, uaddr,
      44  		(unsigned) val3, rc);
      45  }
      46  
      47  # define CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, \
      48  	enosys) \
      49  	do { \
      50  		errno = 0; \
      51  		rc = syscall(__NR_futex, (uaddr), (op), (val), (timeout), \
      52  			(uaddr2), (val3)); \
      53  		/* It is here due to EPERM on WAKE_OP on AArch64 */ \
      54  		if ((rc == -1) && (errno == EPERM)) \
      55  			break; \
      56  		if (enosys && (rc == -1) && (errno == ENOSYS)) \
      57  			break; \
      58  		if (!(check)) \
      59  			futex_error((uaddr), (op), (val), \
      60  				(unsigned long) (timeout), (int *) (uaddr2), \
      61  				(val3), rc, __func__, __LINE__); \
      62  	} while (0)
      63  
      64  # define CHECK_FUTEX_ENOSYS(uaddr, op, val, timeout, uaddr2, val3, check) \
      65  	CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, 1)
      66  
      67  # define CHECK_FUTEX(uaddr, op, val, timeout, uaddr2, val3, check) \
      68  	CHECK_FUTEX_GENERIC(uaddr, op, val, timeout, uaddr2, val3, check, 0)
      69  
      70  enum argmask {
      71  	ARG3 = 1 << 0,
      72  	ARG4 = 1 << 1,
      73  	ARG5 = 1 << 2,
      74  	ARG6 = 1 << 3,
      75  };
      76  
      77  static void
      78  invalid_op(int *val, int op, uint32_t argmask, ...)
      79  {
      80  	static const unsigned long args[] = {
      81  		(unsigned long) 0xface1e55deadbee1ULL,
      82  		(unsigned long) 0xface1e56deadbee2ULL,
      83  		(unsigned long) 0xface1e57deadbee3ULL,
      84  		(unsigned long) 0xface1e58deadbee4ULL,
      85  	};
      86  	/* Since timeout value is copied before full op check, we should provide
      87  	 * some valid timeout address or NULL */
      88  	int cmd = op & FUTEX_CMD_MASK;
      89  	bool valid_timeout = (cmd == FUTEX_WAIT) || (cmd == FUTEX_LOCK_PI) || \
      90  		(cmd == FUTEX_LOCK_PI2) || (cmd == FUTEX_WAIT_BITSET) || \
      91  		(cmd == FUTEX_WAIT_REQUEUE_PI);
      92  	bool timeout_is_val2 = (cmd == FUTEX_REQUEUE) ||
      93  		(cmd == FUTEX_CMP_REQUEUE) || (cmd == FUTEX_WAKE_OP) ||
      94  		(cmd == FUTEX_CMP_REQUEUE_PI);
      95  	const char *fmt;
      96  	int saved_errno;
      97  	int rc;
      98  	va_list ap;
      99  
     100  
     101  	CHECK_FUTEX(val, op, args[0], valid_timeout ? 0 : args[1], args[2],
     102  		args[3], (rc == -1) && (errno == ENOSYS));
     103  	saved_errno = errno;
     104  	printf("futex(%p, %#x /* FUTEX_??? */", val, op);
     105  
     106  	va_start(ap, argmask);
     107  
     108  	for (int i = 0; i < 4; ++i) {
     109  		if (argmask & (1 << i)) {
     110  			fmt = va_arg(ap, const char *);
     111  
     112  			printf(", ");
     113  
     114  			if (((1 << i) == ARG3) || ((1 << i) == ARG6) ||
     115  			    (((1 << i) == ARG4) && timeout_is_val2))
     116  				printf(fmt, (unsigned) args[i]);
     117  			else
     118  				printf(fmt, args[i]);
     119  		}
     120  	}
     121  
     122  	va_end(ap);
     123  
     124  	errno = saved_errno;
     125  	printf(") = -1 ENOSYS (%m)\n");
     126  }
     127  
     128  # define CHECK_INVALID_CLOCKRT(op, ...) \
     129  	do { \
     130  		invalid_op(uaddr, FUTEX_CLOCK_REALTIME | (op), __VA_ARGS__); \
     131  		invalid_op(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG | \
     132  			(op), __VA_ARGS__); \
     133  	} while (0)
     134  
     135  /* Value which differs from one stored in int *val */
     136  # define VAL      ((unsigned long) 0xbadda7a0facefeedLLU)
     137  # define VAL_PR   ((unsigned) VAL)
     138  
     139  # define VALP     ((unsigned long) 0xbadda7a01acefeedLLU)
     140  # define VALP_PR  ((unsigned) VALP)
     141  
     142  # define VAL2     ((unsigned long) 0xbadda7a0ca7b100dLLU)
     143  # define VAL2_PR  ((unsigned) VAL2)
     144  
     145  # define VAL2P    ((unsigned long) 0xbadda7a07a7b100dLLU)
     146  # define VAL2P_PR ((unsigned) VAL2P)
     147  
     148  # define VAL3     ((unsigned long) 0xbadda7a09caffee1LLU)
     149  # define VAL3_PR  ((unsigned) VAL3)
     150  
     151  # define VAL3A    ((unsigned long) 0xbadda7a0ffffffffLLU)
     152  # define VAL3A_PR "FUTEX_BITSET_MATCH_ANY"
     153  
     154  int
     155  main(int argc, char *argv[])
     156  {
     157  	TAIL_ALLOC_OBJECT_CONST_PTR(int, uaddr);
     158  	TAIL_ALLOC_OBJECT_CONST_PTR(int, uaddr2);
     159  	int rc;
     160  
     161  	uaddr[0] = 0x1deadead;
     162  	uaddr2[0] = 0xbadf00d;
     163  
     164  	TAIL_ALLOC_OBJECT_CONST_PTR(kernel_old_timespec_t, tmout);
     165  	tmout->tv_sec = 123;
     166  	tmout->tv_nsec = 0xbadc0de;
     167  
     168  	/* FUTEX_WAIT - check whether uaddr == val and sleep
     169  	 * Possible flags: PRIVATE, CLOCK_RT (since 4.5)
     170  	 * 1. uaddr   - futex address
     171  	 * 2. op      - FUTEX_WAIT
     172  	 * 3. val     - expected value
     173  	 * 4. timeout - address to timespec with timeout
     174  	 * 5. uaddr2  - not used
     175  	 * 6. val3    - not used
     176  	 */
     177  
     178  	/* uaddr is NULL */
     179  	CHECK_FUTEX(NULL, FUTEX_WAIT, VAL, tmout, uaddr2, VAL3,
     180  		(rc == -1) && (errno == EFAULT));
     181  	printf("futex(NULL, FUTEX_WAIT, %u, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     182  	       VAL_PR, (long long) tmout->tv_sec,
     183  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     184  
     185  	/* uaddr is faulty */
     186  	CHECK_FUTEX(uaddr + 1, FUTEX_WAIT, VAL, tmout, uaddr2, VAL3,
     187  		(rc == -1) && (errno == EFAULT));
     188  	printf("futex(%p, FUTEX_WAIT, %u, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     189  	       uaddr + 1, VAL_PR, (long long) tmout->tv_sec,
     190  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     191  
     192  	/* timeout is faulty */
     193  	CHECK_FUTEX(uaddr, FUTEX_WAIT, VAL, tmout + 1, uaddr2, VAL3,
     194  		(rc == -1) && (errno == EFAULT));
     195  	printf("futex(%p, FUTEX_WAIT, %u, %p) = %s\n",
     196  	       uaddr, 0xfacefeed, tmout + 1, sprintrc(rc));
     197  
     198  	/* timeout is invalid */
     199  	tmout->tv_sec = 0xdeadbeefU;
     200  	tmout->tv_nsec = 0xfacefeedU;
     201  
     202  	CHECK_FUTEX(uaddr, FUTEX_WAIT, VAL, tmout, uaddr2, VAL3,
     203  		(rc == -1) && (errno == EINVAL));
     204  	printf("futex(%p, FUTEX_WAIT, %u, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     205  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     206  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     207  
     208  	tmout->tv_sec = (typeof(tmout->tv_sec)) 0xcafef00ddeadbeefLL;
     209  	tmout->tv_nsec = (long) 0xbadc0dedfacefeedLL;
     210  
     211  	CHECK_FUTEX(uaddr, FUTEX_WAIT, VAL, tmout, uaddr2, VAL3,
     212  		(rc == -1) && (errno == EINVAL));
     213  	printf("futex(%p, FUTEX_WAIT, %u, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     214  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     215  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     216  
     217  	tmout->tv_sec = 123;
     218  	tmout->tv_nsec = 0xbadc0de;
     219  
     220  	/* uaddr is not as provided; uaddr2 is faulty but ignored */
     221  	CHECK_FUTEX(uaddr, FUTEX_WAIT, VAL, tmout, uaddr2 + 1, VAL3,
     222  		(rc == -1) && (errno == EAGAIN));
     223  	printf("futex(%p, FUTEX_WAIT, %u, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     224  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     225  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     226  
     227  	/* uaddr is not as provided; uaddr2 is faulty but ignored */
     228  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_WAIT, VAL, tmout,
     229  		uaddr2 + 1, VAL3, (rc == -1) && (errno == EAGAIN));
     230  	printf("futex(%p, FUTEX_WAIT_PRIVATE, %u, {tv_sec=%lld, tv_nsec=%llu})"
     231  	       " = %s\n",
     232  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     233  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     234  
     235  	/* Next 2 tests are with CLOCKRT bit set */
     236  
     237  	/* Valid after v4.4-rc2-27-g337f130 */
     238  	CHECK_FUTEX_ENOSYS(uaddr,
     239  		FUTEX_CLOCK_REALTIME | FUTEX_WAIT,
     240  		VAL, tmout, uaddr2, VAL3, (rc == -1) && (errno == EAGAIN));
     241  	printf("futex(%p, FUTEX_WAIT|FUTEX_CLOCK_REALTIME, %u"
     242  	       ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     243  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     244  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     245  
     246  	CHECK_FUTEX_ENOSYS(uaddr,
     247  		FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG | FUTEX_WAIT,
     248  		VAL, tmout, uaddr2, 0, (rc == -1) && (errno == EAGAIN));
     249  	printf("futex(%p, FUTEX_WAIT_PRIVATE|FUTEX_CLOCK_REALTIME, %u"
     250  	       ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     251  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     252  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     253  
     254  	/* FUTEX_WAIT_BITSET - FUTEX_WAIT which provides additional bitmask
     255  	 *                     which should be matched at least in one bit with
     256  	 *                     wake mask in order to wake.
     257  	 * Possible flags: PRIVATE, CLOCKRT
     258  	 * 1. uaddr   - futex address
     259  	 * 2. op      - FUTEX_TRYLOCK_PI
     260  	 * 3. val     - expected value stored in uaddr
     261  	 * 4. timeout - timeout
     262  	 * 5. uaddr2  - not used
     263  	 * 6. val3    - bitmask
     264  	 */
     265  
     266  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAIT_BITSET, VAL, tmout, uaddr2 + 1,
     267  		VAL3, (rc == -1) && (errno == EAGAIN));
     268  	printf("futex(%p, FUTEX_WAIT_BITSET, %u, {tv_sec=%lld, tv_nsec=%llu}"
     269  	       ", %#x) = %s\n",
     270  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     271  	       zero_extend_signed_to_ull(tmout->tv_nsec), VAL3_PR,
     272  	       sprintrc(rc));
     273  
     274  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAIT_BITSET, VAL, tmout, uaddr2 + 1,
     275  		VAL3A, (rc == -1) && (errno == EAGAIN));
     276  	printf("futex(%p, FUTEX_WAIT_BITSET, %u, {tv_sec=%lld, tv_nsec=%llu}"
     277  	       ", %s) = %s\n",
     278  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     279  	       zero_extend_signed_to_ull(tmout->tv_nsec), VAL3A_PR,
     280  	       sprintrc(rc));
     281  
     282  	/* val3 of 0 is invalid  */
     283  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAIT_BITSET, VAL, tmout, uaddr2 + 1, 0,
     284  		(rc == -1) && (errno == EINVAL));
     285  	printf("futex(%p, FUTEX_WAIT_BITSET, %u, {tv_sec=%lld, tv_nsec=%llu}"
     286  	       ", %#x) = %s\n",
     287  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     288  	       zero_extend_signed_to_ull(tmout->tv_nsec), 0, sprintrc(rc));
     289  
     290  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_WAIT_BITSET, VAL,
     291  		tmout, uaddr2 + 1, VAL3, (rc == -1) && (errno == EAGAIN));
     292  	printf("futex(%p, FUTEX_WAIT_BITSET_PRIVATE, %u"
     293  	       ", {tv_sec=%lld, tv_nsec=%llu}, %#x) = %s\n",
     294  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     295  	       zero_extend_signed_to_ull(tmout->tv_nsec), VAL3_PR,
     296  	       sprintrc(rc));
     297  
     298  	/* Next 3 tests are with CLOCKRT bit set */
     299  
     300  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_WAIT_BITSET, VAL,
     301  		tmout, uaddr2 + 1, VAL3, (rc == -1) && (errno == EAGAIN));
     302  	printf("futex(%p, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %u"
     303  	       ", {tv_sec=%lld, tv_nsec=%llu}, %#x) = %s\n",
     304  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     305  	       zero_extend_signed_to_ull(tmout->tv_nsec), VAL3_PR,
     306  	       sprintrc(rc));
     307  
     308  	/* val3 of 0 is invalid  */
     309  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_WAIT_BITSET, VAL,
     310  		tmout, uaddr2 + 1, 0, (rc == -1) && (errno == EINVAL));
     311  	printf("futex(%p, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %u"
     312  	       ", {tv_sec=%lld, tv_nsec=%llu}, %#x) = %s\n",
     313  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     314  	       zero_extend_signed_to_ull(tmout->tv_nsec), 0, sprintrc(rc));
     315  
     316  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG |
     317  		FUTEX_WAIT_BITSET, VAL, tmout, uaddr2 + 1, VAL3,
     318  		(rc == -1) && (errno == EAGAIN));
     319  	printf("futex(%p, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, %u"
     320  	       ", {tv_sec=%lld, tv_nsec=%llu}, %#x) = %s\n",
     321  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     322  	       zero_extend_signed_to_ull(tmout->tv_nsec), VAL3_PR,
     323  	       sprintrc(rc));
     324  
     325  	/* FUTEX_WAKE - wake val processes waiting for uaddr
     326  	 * Possible flags: PRIVATE
     327  	 * 1. uaddr   - futex address
     328  	 * 2. op      - FUTEX_WAKE
     329  	 * 3. val     - how many processes to wake
     330  	 * 4. timeout - not used
     331  	 * 5. uaddr2  - not used
     332  	 * 6. val3    - not used
     333  	 */
     334  
     335  	/* Zero processes to wake is not a good idea, but it should return 0 */
     336  	CHECK_FUTEX(uaddr, FUTEX_WAKE, 0, NULL, NULL, 0, (rc == 0));
     337  	printf("futex(%p, FUTEX_WAKE, %u) = %s\n", uaddr, 0, sprintrc(rc));
     338  
     339  	/* Trying to wake some processes, but there's nothing to wake */
     340  	CHECK_FUTEX(uaddr, FUTEX_WAKE, 10, NULL, NULL, 0, (rc == 0));
     341  	printf("futex(%p, FUTEX_WAKE, %u) = %s\n", uaddr, 10, sprintrc(rc));
     342  
     343  	/* Trying to wake some processes, but there's nothing to wake */
     344  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_WAKE, 10, NULL,
     345  		NULL, 0, (rc == 0));
     346  	printf("futex(%p, FUTEX_WAKE_PRIVATE, %u) = %s\n", uaddr, 10,
     347  		sprintrc(rc));
     348  
     349  	CHECK_INVALID_CLOCKRT(FUTEX_WAKE, ARG3, "%u");
     350  
     351  	/* FUTEX_WAKE_BITSET - wake val processes waiting for uaddr which has at
     352  	 *                     least one common bit with bitset provided in
     353  	 *                     val3.
     354  	 * Possible flags: PRIVATE
     355  	 * 1. uaddr   - futex address
     356  	 * 2. op      - FUTEX_WAKE
     357  	 * 3. val     - how many processes to wake
     358  	 * 4. timeout - not used
     359  	 * 5. uaddr2  - not used
     360  	 * 6. val3    - bitmask
     361  	 */
     362  
     363  	/* Trying to wake some processes, but there's nothing to wake */
     364  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAKE_BITSET, 10, NULL, NULL,
     365  		VAL3, (rc == 0));
     366  	printf("futex(%p, FUTEX_WAKE_BITSET, %u, %#x) = %s\n", uaddr, 10,
     367  		VAL3_PR, sprintrc(rc));
     368  
     369  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAKE_BITSET, 10, NULL, NULL,
     370  		VAL3A, (rc == 0));
     371  	printf("futex(%p, FUTEX_WAKE_BITSET, %u, %s) = %s\n", uaddr, 10,
     372  		VAL3A_PR, sprintrc(rc));
     373  
     374  	/* bitset 0 is invalid */
     375  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAKE_BITSET, 10, NULL, NULL, 0,
     376  		(rc == -1) && (errno == EINVAL));
     377  	printf("futex(%p, FUTEX_WAKE_BITSET, %u, %#x) = %s\n", uaddr, 10, 0,
     378  		sprintrc(rc));
     379  
     380  	/* Trying to wake some processes, but there's nothing to wake */
     381  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_WAKE_BITSET, 10,
     382  		NULL, NULL, VAL3, (rc == 0));
     383  	printf("futex(%p, FUTEX_WAKE_BITSET_PRIVATE, %u, %#x) = %s\n", uaddr,
     384  		10, VAL3_PR, sprintrc(rc));
     385  
     386  	CHECK_INVALID_CLOCKRT(FUTEX_WAKE_BITSET, ARG3 | ARG6, "%u", "%#x");
     387  
     388  	/* FUTEX_FD - deprecated
     389  	 * Possible flags: PRIVATE
     390  	 * 1. uaddr   - futex address
     391  	 * 2. op      - FUTEX_FD
     392  	 * 3. val     - signal number
     393  	 * 4. timeout - not used
     394  	 * 5. uaddr2  - not used
     395  	 * 6. val3    - not used
     396  	 */
     397  
     398  	/* FUTEX_FD is not implemented since 2.6.26 */
     399  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_FD, VAL, NULL, NULL, VAL3,
     400  		(rc == -1) && (errno == EINVAL));
     401  	printf("futex(%p, FUTEX_FD, %u) = %s\n", uaddr, VAL_PR, sprintrc(rc));
     402  
     403  	/* FUTEX_FD is not implemented since 2.6.26 */
     404  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_FD, VAL, NULL,
     405  		NULL, VAL3, (rc == -1) && (errno == EINVAL));
     406  	printf("futex(%p, FUTEX_FD|FUTEX_PRIVATE_FLAG, %u) = %s\n", uaddr,
     407  		VAL_PR, sprintrc(rc));
     408  
     409  	CHECK_INVALID_CLOCKRT(FUTEX_FD, ARG3, "%u");
     410  
     411  	/* FUTEX_REQUEUE - wake val processes and re-queue rest on uaddr2
     412  	 * Possible flags: PRIVATE
     413  	 * 1. uaddr   - futex address
     414  	 * 2. op      - FUTEX_REQUEUE
     415  	 * 3. val     - how many processes to wake
     416  	 * 4. val2    - amount of processes to re-queue on uadr2
     417  	 * 5. uaddr2  - another futex address, to re-queue waiting processes on
     418  	 * 6. val3    - not used
     419  	 */
     420  
     421  	/* Trying to re-queue some processes but there's nothing to re-queue */
     422  	CHECK_FUTEX(uaddr, FUTEX_REQUEUE, VAL, VAL2, uaddr2, VAL3,
     423  		(rc == 0) || ((rc == -1) && (errno == EINVAL)));
     424  	printf("futex(%p, FUTEX_REQUEUE, %u, %u, %p) = %s\n",
     425  		uaddr, VAL_PR, VAL2_PR, uaddr2, sprintrc(rc));
     426  
     427  	CHECK_FUTEX(uaddr, FUTEX_REQUEUE, VALP, VAL2P, uaddr2, VAL3,
     428  		(rc == 0));
     429  	printf("futex(%p, FUTEX_REQUEUE, %u, %u, %p) = %s\n",
     430  		uaddr, VALP_PR, VAL2P_PR, uaddr2, sprintrc(rc));
     431  
     432  	/* Trying to re-queue some processes but there's nothing to re-queue */
     433  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_REQUEUE, VAL, VAL2,
     434  		uaddr2, VAL3, (rc == 0) || ((rc == -1) && (errno == EINVAL)));
     435  	printf("futex(%p, FUTEX_REQUEUE_PRIVATE, %u, %u, %p) = %s\n",
     436  		uaddr, VAL_PR, VAL2_PR, uaddr2, sprintrc(rc));
     437  
     438  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_REQUEUE, VALP,
     439  		VAL2P, uaddr2, VAL3, (rc == 0));
     440  	printf("futex(%p, FUTEX_REQUEUE_PRIVATE, %u, %u, %p) = %s\n",
     441  		uaddr, VALP_PR, VAL2P_PR, uaddr2, sprintrc(rc));
     442  
     443  	CHECK_INVALID_CLOCKRT(FUTEX_REQUEUE, ARG3 | ARG4 | ARG5, "%u", "%u",
     444  		"%#lx");
     445  
     446  	/* FUTEX_CMP_REQUEUE - wake val processes and re-queue rest on uaddr2
     447  	 *                     if uaddr has value val3
     448  	 * Possible flags: PRIVATE
     449  	 * 1. uaddr   - futex address
     450  	 * 2. op      - FUTEX_CMP_REQUEUE
     451  	 * 3. val     - how many processes to wake
     452  	 * 4. val2    - amount of processes to re-queue on uadr2
     453  	 * 5. uaddr2  - another futex address, to re-queue waiting processes on
     454  	 * 6. val3    - expected value stored in uaddr
     455  	 */
     456  
     457  	/* Comparison re-queue with wrong val value */
     458  	CHECK_FUTEX(uaddr, FUTEX_CMP_REQUEUE, VAL, VAL2, uaddr2, VAL3,
     459  		(rc == -1) && (errno == EAGAIN || errno == EINVAL));
     460  	printf("futex(%p, FUTEX_CMP_REQUEUE, %u, %u, %p, %u) = %s\n",
     461  		uaddr, VAL_PR, VAL2_PR, uaddr2, VAL3_PR, sprintrc(rc));
     462  
     463  	CHECK_FUTEX(uaddr, FUTEX_CMP_REQUEUE, VALP, VAL2P, uaddr2, VAL3,
     464  		(rc == -1) && (errno == EAGAIN));
     465  	printf("futex(%p, FUTEX_CMP_REQUEUE, %u, %u, %p, %u) = %s\n",
     466  		uaddr, VALP_PR, VAL2P_PR, uaddr2, VAL3_PR, sprintrc(rc));
     467  
     468  	/* Successful comparison re-queue */
     469  	CHECK_FUTEX(uaddr, FUTEX_CMP_REQUEUE, VAL, VAL2, uaddr2, *uaddr,
     470  		(rc == 0) || ((rc == -1) && (errno == EINVAL)));
     471  	printf("futex(%p, FUTEX_CMP_REQUEUE, %u, %u, %p, %u) = %s\n",
     472  		uaddr, VAL_PR, VAL2_PR, uaddr2, *uaddr, sprintrc(rc));
     473  
     474  	CHECK_FUTEX(uaddr, FUTEX_CMP_REQUEUE, VALP, VAL2P, uaddr2, *uaddr,
     475  		(rc == 0));
     476  	printf("futex(%p, FUTEX_CMP_REQUEUE, %u, %u, %p, %u) = %s\n",
     477  		uaddr, VALP_PR, VAL2P_PR, uaddr2, *uaddr, sprintrc(rc));
     478  
     479  	/* Successful comparison re-queue */
     480  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_CMP_REQUEUE, VAL,
     481  		VAL2, uaddr2, *uaddr,
     482  		(rc == 0) || ((rc == -1) && (errno == EINVAL)));
     483  	printf("futex(%p, FUTEX_CMP_REQUEUE_PRIVATE, %u, %u, %p, %u) = %s\n",
     484  		uaddr, VAL_PR, VAL2_PR, uaddr2, *uaddr, sprintrc(rc));
     485  
     486  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_CMP_REQUEUE, VALP,
     487  		VAL2P, uaddr2, *uaddr, (rc == 0));
     488  	printf("futex(%p, FUTEX_CMP_REQUEUE_PRIVATE, %u, %u, %p, %u) = %s\n",
     489  		uaddr, VALP_PR, VAL2P_PR, uaddr2, *uaddr, sprintrc(rc));
     490  
     491  	CHECK_INVALID_CLOCKRT(FUTEX_CMP_REQUEUE, ARG3 | ARG4 | ARG5 | ARG6,
     492  		"%u", "%u", "%#lx", "%u");
     493  
     494  	/* FUTEX_WAKE_OP - wake val processes waiting for uaddr, additionally
     495  	 *                 wake val2 processes waiting for uaddr2 in case
     496  	 *                 operation encoded in val3 (change of value at uaddr2
     497  	 *                 and comparison of previous value against provided
     498  	 *                 constant) succeeds with value at uaddr2. Operation
     499  	 *                 result is written to value of uaddr2 (in any case).
     500  	 * 1. uaddr   - futex address
     501  	 * 2. op      - FUTEX_WAKE_OP
     502  	 * 3. val     - how many processes to wake
     503  	 * 4. val2    - amount of processes to wake in case operation encoded in
     504  	 *              val3 returns true
     505  	 * 5. uaddr2  - another futex address, for conditional wake of
     506  	 *              additional processes
     507  	 * 6. val3    - encoded operation:
     508  	 *                1. bit 31 - if 1 then value stored in field field 4
     509  	 *                            should be interpreted as power of 2.
     510  	 *                2. 28..30 - arithmetic operation which should be
     511  	 *                            applied to previous value stored in
     512  	 *                            uaddr2. Values available (from 2005 up to
     513  	 *                            2016): SET. ADD, OR, ANDN, XOR.
     514  	 *                3. 24..29 - comparison operation which should be
     515  	 *                            applied to the old value stored in uaddr2
     516  	 *                            (before arithmetic operation is applied).
     517  	 *                            Possible values: EQ, NE, LT, LE, GT, GE.
     518  	 *                4. 12..23 - Second operand for arithmetic operation.
     519  	 *                            If bit 31 is set, it is interpreted as
     520  	 *                            power of 2.
     521  	 *                5. 00..11 - Value against which old value stored in
     522  	 *                            uaddr2 is compared.
     523  	 */
     524  
     525  	static const struct {
     526  		uint32_t val;
     527  		const char *str;
     528  
     529  		/*
     530  		 * Peculiar semantics:
     531  		 *  * err == 0 and err2 != 0 => expect both either the absence
     532  		 *    of error or presence of err2
     533  		 *  * err != 0 and err2 == 0 => expect err only, no success
     534  		 *    expected.
     535  		 */
     536  		int err;
     537  		int err2;
     538  	} wake_ops[] = {
     539  		{ 0x00000000, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_EQ<<24|0" },
     540  		{ 0x00fff000, "FUTEX_OP_SET<<28|0xfff<<12|FUTEX_OP_CMP_EQ<<24|"
     541  			"0" },
     542  		{ 0x00000fff, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_EQ<<24|"
     543  			"0xfff" },
     544  		{ 0x00ffffff, "FUTEX_OP_SET<<28|0xfff<<12|FUTEX_OP_CMP_EQ<<24|"
     545  			"0xfff" },
     546  		{ 0x10000000, "FUTEX_OP_ADD<<28|0<<12|FUTEX_OP_CMP_EQ<<24|0" },
     547  		{ 0x20000000, "FUTEX_OP_OR<<28|0<<12|FUTEX_OP_CMP_EQ<<24|0" },
     548  		{ 0x30000000, "FUTEX_OP_ANDN<<28|0<<12|FUTEX_OP_CMP_EQ<<24|0" },
     549  		{ 0x40000000, "FUTEX_OP_XOR<<28|0<<12|FUTEX_OP_CMP_EQ<<24|0" },
     550  		{ 0x50000000, "0x5<<28 /* FUTEX_OP_??? */|0<<12|"
     551  			"FUTEX_OP_CMP_EQ<<24|0", ENOSYS },
     552  		{ 0x70000000, "0x7<<28 /* FUTEX_OP_??? */|0<<12|"
     553  			"FUTEX_OP_CMP_EQ<<24|0", ENOSYS },
     554  		{ 0x80000000, "FUTEX_OP_OPARG_SHIFT<<28|FUTEX_OP_SET<<28|0<<12|"
     555  			"FUTEX_OP_CMP_EQ<<24|0" },
     556  		{ 0xa0caffee, "FUTEX_OP_OPARG_SHIFT<<28|FUTEX_OP_OR<<28|"
     557  			"0xcaf<<12|FUTEX_OP_CMP_EQ<<24|0xfee", 0, EINVAL },
     558  		{ 0x01000000, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_NE<<24|0" },
     559  		{ 0x01234567, "FUTEX_OP_SET<<28|0x234<<12|FUTEX_OP_CMP_NE<<24|"
     560  			"0x567" },
     561  		{ 0x02000000, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_LT<<24|0" },
     562  		{ 0x03000000, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_LE<<24|0" },
     563  		{ 0x04000000, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_GT<<24|0" },
     564  		{ 0x05000000, "FUTEX_OP_SET<<28|0<<12|FUTEX_OP_CMP_GE<<24|0" },
     565  		{ 0x06000000, "FUTEX_OP_SET<<28|0<<12|"
     566  			"0x6<<24 /* FUTEX_OP_CMP_??? */|0", ENOSYS },
     567  		{ 0x07000000, "FUTEX_OP_SET<<28|0<<12|"
     568  			"0x7<<24 /* FUTEX_OP_CMP_??? */|0", ENOSYS },
     569  		{ 0x08000000, "FUTEX_OP_SET<<28|0<<12|"
     570  			"0x8<<24 /* FUTEX_OP_CMP_??? */|0", ENOSYS },
     571  		{ 0x0f000000, "FUTEX_OP_SET<<28|0<<12|"
     572  			"0xf<<24 /* FUTEX_OP_CMP_??? */|0", ENOSYS },
     573  		{ 0xbadfaced, "FUTEX_OP_OPARG_SHIFT<<28|FUTEX_OP_ANDN<<28|"
     574  			"0xdfa<<12|0xa<<24 /* FUTEX_OP_CMP_??? */|0xced",
     575  			ENOSYS, EINVAL },
     576  		{ 0xffffffff, "FUTEX_OP_OPARG_SHIFT<<28|"
     577  			"0x7<<28 /* FUTEX_OP_??? */|0xfff<<12|"
     578  			"0xf<<24 /* FUTEX_OP_CMP_??? */|0xfff",
     579  			ENOSYS, EINVAL },
     580  	};
     581  
     582  	for (unsigned int i = 0; i < ARRAY_SIZE(wake_ops); ++i) {
     583  		for (unsigned int j = 0; j < 2; ++j) {
     584  			CHECK_FUTEX_ENOSYS(uaddr,
     585  				j ? FUTEX_WAKE_OP_PRIVATE : FUTEX_WAKE_OP,
     586  				VAL, i, uaddr2, wake_ops[i].val,
     587  				/*
     588  				 * Either one of errs is 0 or rc == 0 is not
     589  				 * allowed.
     590  				 */
     591  				((!wake_ops[i].err || !wake_ops[i].err2 ||
     592  					(rc != 0)) &&
     593  				((!wake_ops[i].err && (rc == 0)) ||
     594  				(wake_ops[i].err  && (rc == -1) &&
     595  					(errno == wake_ops[i].err)) ||
     596  				(wake_ops[i].err2 && (rc == -1) &&
     597  					(errno == wake_ops[i].err2)))));
     598  			printf("futex(%p, FUTEX_WAKE_OP%s, %u, %u, %p, %s)"
     599  			       " = %s\n", uaddr, j ? "_PRIVATE" : "", VAL_PR,
     600  			       i, uaddr2, wake_ops[i].str, sprintrc(rc));
     601  		}
     602  	}
     603  
     604  	CHECK_INVALID_CLOCKRT(FUTEX_WAKE_OP, ARG3 | ARG4 | ARG5 | ARG6,
     605  		"%u", "%u", "%#lx",
     606  		/* Decoding of the 0xdeadbee4 value */
     607  		"FUTEX_OP_OPARG_SHIFT<<28|0x5<<28 /* FUTEX_OP_??? */|0xadb<<12|"
     608  		"0xe<<24 /* FUTEX_OP_CMP_??? */|0xee4");
     609  
     610  	/* FUTEX_LOCK_PI - slow path for mutex lock with process inheritance
     611  	 *                 support. Expect that futex has 0 in unlocked case and
     612  	 *                 TID of owning process in locked case. Value can also
     613  	 *                 contain FUTEX_WAITERS bit signalling the presence of
     614  	 *                 waiters queue.
     615  	 * Possible flags: PRIVATE
     616  	 * 1. uaddr   - futex address
     617  	 * 2. op      - FUTEX_LOCK_PI
     618  	 * 3. val     - not used
     619  	 * 4. timeout - timeout
     620  	 * 5. uaddr2  - not used
     621  	 * 6. val3    - not used
     622  	 */
     623  
     624  	*uaddr = getpid();
     625  
     626  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_LOCK_PI, VAL, tmout, uaddr2 + 1,
     627  		VAL3, (rc == -1) && (errno == EFAULT));
     628  	printf("futex(%p, FUTEX_LOCK_PI, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     629  	       uaddr + 1, (long long) tmout->tv_sec,
     630  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     631  
     632  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_PRIVATE_FLAG | FUTEX_LOCK_PI, VAL,
     633  		tmout, uaddr2 + 1, VAL3, (rc == -1) && (errno == EFAULT));
     634  	printf("futex(%p, FUTEX_LOCK_PI_PRIVATE, {tv_sec=%lld, tv_nsec=%llu})"
     635  	       " = %s\n",
     636  	       uaddr + 1, (long long) tmout->tv_sec,
     637  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     638  
     639  	/* NULL is passed by invalid_op() in cases valid timeout address is
     640  	 * needed */
     641  	CHECK_INVALID_CLOCKRT(FUTEX_LOCK_PI, ARG4, "NULL");
     642  
     643  	/* FUTEX_UNLOCK_PI - slow path for mutex unlock with process inheritance
     644  	 *                   support. Expected to be called by process in case
     645  	 *                   it failed to execute fast path (it usually means
     646  	 *                   that FUTEX_WAITERS flag had been set while the lock
     647  	 *                   has been held).
     648  	 * Possible flags: PRIVATE
     649  	 * 1. uaddr   - futex address
     650  	 * 2. op      - FUTEX_UNLOCK_PI
     651  	 * 3. val     - not used
     652  	 * 4. timeout - not used
     653  	 * 5. uaddr2  - not used
     654  	 * 6. val3    - not used
     655  	 */
     656  
     657  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_UNLOCK_PI, VAL, tmout, uaddr2 + 1,
     658  		VAL3, (rc == -1) && (errno == EFAULT));
     659  	printf("futex(%p, FUTEX_UNLOCK_PI) = %s\n", uaddr + 1, sprintrc(rc));
     660  
     661  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_PRIVATE_FLAG | FUTEX_UNLOCK_PI, VAL,
     662  		tmout, uaddr2 + 1, VAL3, (rc == -1) && (errno == EFAULT));
     663  	printf("futex(%p, FUTEX_UNLOCK_PI_PRIVATE) = %s\n", uaddr + 1,
     664  		sprintrc(rc));
     665  
     666  	CHECK_INVALID_CLOCKRT(FUTEX_UNLOCK_PI, 0);
     667  
     668  	/* FUTEX_TRYLOCK_PI - slow path for mutex trylock with process
     669  	 *                 inheritance support.
     670  	 * Possible flags: PRIVATE
     671  	 * 1. uaddr   - futex address
     672  	 * 2. op      - FUTEX_TRYLOCK_PI
     673  	 * 3. val     - not used
     674  	 * 4. timeout - not used
     675  	 * 5. uaddr2  - not used
     676  	 * 6. val3    - not used
     677  	 */
     678  
     679  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_TRYLOCK_PI, VAL, tmout, uaddr2 + 1,
     680  		VAL3, (rc == -1) && (errno == EFAULT));
     681  	printf("futex(%p, FUTEX_TRYLOCK_PI) = %s\n", uaddr + 1, sprintrc(rc));
     682  
     683  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_PRIVATE_FLAG | FUTEX_TRYLOCK_PI,
     684  		VAL, tmout, uaddr2 + 1, VAL3, (rc == -1) && (errno == EFAULT));
     685  	printf("futex(%p, FUTEX_TRYLOCK_PI_PRIVATE) = %s\n", uaddr + 1,
     686  		sprintrc(rc));
     687  
     688  	CHECK_INVALID_CLOCKRT(FUTEX_TRYLOCK_PI, 0);
     689  
     690  	/* FUTEX_WAIT_REQUEUE_PI - kernel-side handling of special case when
     691  	 *                         processes should be re-queued on PI-aware
     692  	 *                         futexes. This is so special since PI futexes
     693  	 *                         utilize rt_mutex and it should be at no time
     694  	 *                         left free with a wait queue, so this should
     695  	 *                         be performed atomically in-kernel.
     696  	 * Possible flags: PRIVATE, CLOCKRT
     697  	 * 1. uaddr   - futex address
     698  	 * 2. op      - FUTEX_WAIT_REQUEUE_PI
     699  	 * 3. val     - expected value stored in uaddr
     700  	 * 4. timeout - timeout
     701  	 * 5. uaddr2  - (PI-aware) futex address to requeue process on
     702  	 * 6. val3    - not used (in kernel, it always initialized to
     703  	 *              FUTEX_BITSET_MATCH_ANY and passed to
     704  	 *              futex_wait_requeue_pi())
     705  	 */
     706  
     707  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_WAIT_REQUEUE_PI, VAL, tmout, uaddr2,
     708  		VAL3, (rc == -1) && (errno == EAGAIN));
     709  	printf("futex(%p, FUTEX_WAIT_REQUEUE_PI, %u"
     710  	       ", {tv_sec=%lld, tv_nsec=%llu}, %p) = %s\n",
     711  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     712  	       zero_extend_signed_to_ull(tmout->tv_nsec), uaddr2, sprintrc(rc));
     713  
     714  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_WAIT_REQUEUE_PI,
     715  		VAL, tmout, uaddr2, VAL3, (rc == -1) && (errno == EAGAIN));
     716  	printf("futex(%p, FUTEX_WAIT_REQUEUE_PI_PRIVATE, %u"
     717  	       ", {tv_sec=%lld, tv_nsec=%llu}, %p) = %s\n",
     718  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     719  	       zero_extend_signed_to_ull(tmout->tv_nsec), uaddr2, sprintrc(rc));
     720  
     721  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_WAIT_REQUEUE_PI,
     722  		VAL, tmout, uaddr2, VAL3, (rc == -1) && (errno == EAGAIN));
     723  	printf("futex(%p, FUTEX_WAIT_REQUEUE_PI|FUTEX_CLOCK_REALTIME, %u"
     724  	       ", {tv_sec=%lld, tv_nsec=%llu}, %p) = %s\n",
     725  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     726  	       zero_extend_signed_to_ull(tmout->tv_nsec), uaddr2, sprintrc(rc));
     727  
     728  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG |
     729  		FUTEX_WAIT_REQUEUE_PI, VAL, tmout, uaddr2, VAL3,
     730  		(rc == -1) && (errno == EAGAIN));
     731  	printf("futex(%p, FUTEX_WAIT_REQUEUE_PI_PRIVATE|FUTEX_CLOCK_REALTIME"
     732  	       ", %u, {tv_sec=%lld, tv_nsec=%llu}, %p) = %s\n",
     733  	       uaddr, VAL_PR, (long long) tmout->tv_sec,
     734  	       zero_extend_signed_to_ull(tmout->tv_nsec), uaddr2, sprintrc(rc));
     735  
     736  	/* FUTEX_CMP_REQUEUE_PI - version of FUTEX_CMP_REQUEUE which re-queues
     737  	 *                        on PI-aware futex.
     738  	 * Possible flags: PRIVATE
     739  	 * 1. uaddr   - futex address
     740  	 * 2. op      - FUTEX_CMP_REQUEUE
     741  	 * 3. val     - how many processes to wake
     742  	 * 4. val2    - amount of processes to re-queue on uadr2
     743  	 * 5. uaddr2  - (PI-aware) futex address, to re-queue waiting processes
     744  	 *              on
     745  	 * 6. val3    - expected value stored in uaddr
     746  	 */
     747  
     748  	/* All these should fail with EINVAL since we try to re-queue to  non-PI
     749  	 * futex.
     750  	 */
     751  
     752  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CMP_REQUEUE_PI, VAL, VAL2, uaddr2, VAL3,
     753  		(rc == -1) && (errno == EINVAL));
     754  	printf("futex(%p, FUTEX_CMP_REQUEUE_PI, %u, %u, %p, %u) = %s\n",
     755  		uaddr, VAL_PR, VAL2_PR, uaddr2, VAL3_PR, sprintrc(rc));
     756  
     757  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_CMP_REQUEUE_PI, VAL, VAL2, uaddr2,
     758  		*uaddr, (rc == -1) && (errno == EINVAL));
     759  	printf("futex(%p, FUTEX_CMP_REQUEUE_PI, %u, %u, %p, %u) = %s\n",
     760  		uaddr, VAL_PR, VAL2_PR, uaddr2, *uaddr, sprintrc(rc));
     761  
     762  	CHECK_FUTEX_ENOSYS(uaddr, FUTEX_PRIVATE_FLAG | FUTEX_CMP_REQUEUE_PI,
     763  		VAL, VAL2, uaddr2, *uaddr, (rc == -1) && (errno == EINVAL));
     764  	printf("futex(%p, FUTEX_CMP_REQUEUE_PI_PRIVATE, %u, %u, %p, %u) = %s\n",
     765  		uaddr, VAL_PR, VAL2_PR, uaddr2, *uaddr, sprintrc(rc));
     766  
     767  	CHECK_INVALID_CLOCKRT(FUTEX_CMP_REQUEUE_PI, ARG3 | ARG4 | ARG5 | ARG6,
     768  		"%u", "%u", "%#lx", "%u");
     769  
     770  	/* FUTEX_LOCK_PI2 - same as FUTEX_LOCK_PI, but with CLOCK_MONOTONIC
     771  	 *                  instead of CLOCK_REALTIME.
     772  	 * Possible flags: PRIVATE
     773  	 * 1. uaddr   - futex address
     774  	 * 2. op      - FUTEX_LOCK_PI2
     775  	 * 3. val     - not used
     776  	 * 4. timeout - timeout
     777  	 * 5. uaddr2  - not used
     778  	 * 6. val3    - not used
     779  	 */
     780  
     781  	*uaddr = getpid();
     782  
     783  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_LOCK_PI2, VAL, tmout, uaddr2 + 1,
     784  		VAL3, (rc == -1) && (errno == EFAULT));
     785  	printf("futex(%p, FUTEX_LOCK_PI2, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
     786  	       uaddr + 1, (long long) tmout->tv_sec,
     787  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     788  
     789  	CHECK_FUTEX_ENOSYS(uaddr + 1, FUTEX_PRIVATE_FLAG | FUTEX_LOCK_PI2, VAL,
     790  		tmout, uaddr2 + 1, VAL3, (rc == -1) && (errno == EFAULT));
     791  	printf("futex(%p, FUTEX_LOCK_PI2_PRIVATE, {tv_sec=%lld, tv_nsec=%llu})"
     792  	       " = %s\n",
     793  	       uaddr + 1, (long long) tmout->tv_sec,
     794  	       zero_extend_signed_to_ull(tmout->tv_nsec), sprintrc(rc));
     795  
     796  
     797  	/*
     798  	 * Unknown commands
     799  	 */
     800  
     801  	CHECK_FUTEX(uaddr, 0xe, VAL, tmout + 1, uaddr2 + 1, VAL3,
     802  		(rc == -1) && (errno == ENOSYS));
     803  	printf("futex(%p, 0xe /* FUTEX_??? */, %u, %p, %p, %#x) = %s\n",
     804  		uaddr, VAL_PR, tmout + 1, uaddr2 + 1, VAL3_PR, sprintrc(rc));
     805  
     806  	CHECK_FUTEX(uaddr, 0xbefeeded, VAL, tmout + 1, uaddr2, VAL3,
     807  		(rc == -1) && (errno == ENOSYS));
     808  	printf("futex(%p, 0xbefeeded /* FUTEX_??? */, %u, %p, %p, %#x) = %s\n",
     809  		uaddr, VAL_PR, tmout + 1, uaddr2, VAL3_PR, sprintrc(rc));
     810  
     811  	puts("+++ exited with 0 +++");
     812  
     813  	return 0;
     814  }
     815  
     816  #else
     817  
     818  SKIP_MAIN_UNDEFINED("__NR_futex")
     819  
     820  #endif