• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@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 
futex_error(int * uaddr,int op,unsigned long val,unsigned long timeout,int * uaddr2,unsigned long val3,int rc,const char * func,int line)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 
invalid_op(int * val,int op,uint32_t argmask,...)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
main(int argc,char * argv[])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