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