(root)/
strace-6.5/
tests-m32/
futex_waitv.c
       1  /*
       2   * Check decoding of futex_waitv syscall.
       3   *
       4   * Copyright (c) 2015-2022 Dmitry V. Levin <ldv@strace.io>
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include "scno.h"
      12  #include "kernel_timespec.h"
      13  #include <stdio.h>
      14  #include <stdlib.h>
      15  #include <time.h>
      16  #include <unistd.h>
      17  #include <linux/futex.h>
      18  
      19  static const char *errstr;
      20  
      21  static long
      22  k_futex_waitv(const void *const waiters,
      23  	      const unsigned int nr_futexes,
      24  	      const unsigned int flags,
      25  	      const void *const timeout,
      26  	      const unsigned int clockid)
      27  {
      28  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      29  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      30  	const kernel_ulong_t arg1 = (uintptr_t) waiters;
      31  	const kernel_ulong_t arg2 = fill | nr_futexes;
      32  	const kernel_ulong_t arg3 = fill | flags;
      33  	const kernel_ulong_t arg4 = (uintptr_t) timeout;
      34  	const kernel_ulong_t arg5 = fill | clockid;
      35  	const long rc = syscall(__NR_futex_waitv,
      36  				arg1, arg2, arg3, arg4, arg5, bad);
      37  	errstr = sprintrc(rc);
      38  	return rc;
      39  }
      40  
      41  int
      42  main(void)
      43  {
      44  	TAIL_ALLOC_OBJECT_CONST_PTR(uint32_t, futex);
      45  	TAIL_ALLOC_OBJECT_CONST_PTR(struct futex_waitv, waiter);
      46  	TAIL_ALLOC_OBJECT_CONST_PTR(kernel_timespec64_t, ts);
      47  	ts->tv_sec = 1;
      48  	ts->tv_nsec = 2;
      49  
      50  	k_futex_waitv(0, 1, -1U, 0, 1);
      51  	printf("futex_waitv(NULL, 1, %#x, NULL, CLOCK_MONOTONIC) = %s\n",
      52  	       -1U, errstr);
      53  
      54  	k_futex_waitv(waiter + 1, 0, 1, ts + 1, -1U);
      55  	printf("futex_waitv([], 0, %#x, %p, %#x /* CLOCK_??? */) = %s\n",
      56  	       1, ts + 1, -1U, errstr);
      57  
      58  	k_futex_waitv((void *) waiter + 1, 1, 0, ts, 0);
      59  	printf("futex_waitv(%p, 1, 0, {tv_sec=1, tv_nsec=2}, CLOCK_REALTIME)"
      60  	       " = %s\n",
      61  	       (void *) waiter + 1, errstr);
      62  
      63  	waiter->uaddr = 0;
      64  	k_futex_waitv(waiter, 1, 0, 0, 1);
      65  	printf("futex_waitv([{val=%#llx, uaddr=NULL, flags=%s|%#x"
      66  	       ", __reserved=%#x}], 1, 0, NULL, CLOCK_MONOTONIC) = %s\n",
      67  	       (unsigned long long) waiter->val,
      68  	       "FUTEX_32|FUTEX_PRIVATE_FLAG",
      69  	       waiter->flags & ~(FUTEX_32|FUTEX_PRIVATE_FLAG),
      70  	       waiter->__reserved, errstr);
      71  
      72  	waiter->val = 0xdeadbeeffacefeedULL;
      73  	waiter->uaddr = -1ULL;
      74  	waiter->flags = 0;
      75  	waiter->__reserved = 0;
      76  	k_futex_waitv(waiter, 1, 0, 0, 2);
      77  	printf("futex_waitv([{val=%#llx, uaddr=%#llx, flags=0}], 1, 0, NULL"
      78  	       ", CLOCK_PROCESS_CPUTIME_ID) = %s\n",
      79  	       (unsigned long long) waiter->val,
      80  	       (unsigned long long) waiter->uaddr,
      81  	       errstr);
      82  
      83  	waiter->val = 0;
      84  	waiter->uaddr = (uintptr_t) futex;
      85  	waiter->flags = FUTEX_PRIVATE_FLAG;
      86  	k_futex_waitv(waiter, 1, 0, 0, 0);
      87  	printf("futex_waitv([{val=0, uaddr=%p, flags=%s}], 1, 0, NULL"
      88  	       ", CLOCK_REALTIME) = %s\n",
      89  	       futex, "FUTEX_PRIVATE_FLAG", errstr);
      90  
      91  	waiter->flags = FUTEX_32;
      92  	k_futex_waitv(waiter, 2, 0, 0, 1);
      93  	printf("futex_waitv([{val=0, uaddr=%p, flags=%s}, ... /* %p */], 2, 0, NULL"
      94  	       ", CLOCK_MONOTONIC) = %s\n",
      95  	       futex, "FUTEX_32", waiter + 1, errstr);
      96  
      97  	waiter->flags = FUTEX_32|FUTEX_PRIVATE_FLAG;
      98  	k_futex_waitv(waiter, 1, 0, ts, 1);
      99  	printf("futex_waitv([{val=0, uaddr=%p, flags=%s}], 1, 0"
     100  	       ", {tv_sec=1, tv_nsec=2}, CLOCK_MONOTONIC) = %s\n",
     101  	       futex, "FUTEX_32|FUTEX_PRIVATE_FLAG", errstr);
     102  
     103  	unsigned int nr = FUTEX_WAITV_MAX + 1;
     104  	uint32_t * const futexes = tail_alloc(nr * sizeof(*futexes));
     105  	struct futex_waitv * const waiters = tail_alloc(nr * sizeof(*waiters));
     106  	for (unsigned int i = 0; i < nr; ++i) {
     107  		futexes[i] = i;
     108  		waiters[i].val = i;
     109  		waiters[i].uaddr = (uintptr_t) &futexes[i];
     110  		waiters[i].flags = FUTEX_32|FUTEX_PRIVATE_FLAG;
     111  		waiters[i].__reserved = 0;
     112  	}
     113  	k_futex_waitv(waiters, nr, 0, ts, 1);
     114  	printf("futex_waitv([");
     115  	for (unsigned int i = 0; i < FUTEX_WAITV_MAX; ++i) {
     116  		printf("%s{val=%#x, uaddr=%p, flags=%s}",
     117  		       i ? ", " : "",
     118  		       i, &futexes[i], "FUTEX_32|FUTEX_PRIVATE_FLAG");
     119  	}
     120  	printf(", ...], %u, 0, {tv_sec=1, tv_nsec=2}, CLOCK_MONOTONIC) = %s\n",
     121  	       nr, errstr);
     122  
     123  	nr = FUTEX_WAITV_MAX;
     124  	k_futex_waitv(waiters + 1, nr, 0, ts, 1);
     125  	printf("futex_waitv([");
     126  	for (unsigned int i = 0; i < FUTEX_WAITV_MAX; ++i) {
     127  		printf("%s{val=%#x, uaddr=%p, flags=%s}",
     128  		       i ? ", " : "",
     129  		       i + 1, &futexes[i + 1], "FUTEX_32|FUTEX_PRIVATE_FLAG");
     130  	}
     131  	printf("], %u, 0, {tv_sec=1, tv_nsec=2}, CLOCK_MONOTONIC) = %s\n",
     132  	       nr, errstr);
     133  
     134  	puts("+++ exited with 0 +++");
     135  	return 0;
     136  }