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