summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@strace.io>2022-01-09 00:08:00 +0000
committerDmitry V. Levin <ldv@strace.io>2022-01-09 00:08:00 +0000
commitcd0ea09e3077d7aacadb7d1e8494935ec59ca746 (patch)
tree28385c6f6fb0f23d9d71117039ee296957e6d394
parenta5e03b6c8bb02523c620fef2f13983c800044e80 (diff)
downloadstrace-cd0ea09e3077d7aacadb7d1e8494935ec59ca746.tar.gz
tests: check decoding of futex_waitv syscall
* tests/futex_waitv.c: New file. * tests/gen_tests.in (futex_waitv): New test. * tests/pure_executables.list: Add futex_waitv. * tests/.gitignore: Likewise.
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/futex_waitv.c136
-rw-r--r--tests/gen_tests.in1
-rwxr-xr-xtests/pure_executables.list1
4 files changed, 139 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index ec3090776..128d9a076 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -170,6 +170,7 @@ fsync-y
ftruncate
ftruncate64
futex
+futex_waitv
futimesat
gen_tests.am
get_mempolicy
diff --git a/tests/futex_waitv.c b/tests/futex_waitv.c
new file mode 100644
index 000000000..96f773513
--- /dev/null
+++ b/tests/futex_waitv.c
@@ -0,0 +1,136 @@
+/*
+ * Check decoding of futex_waitv syscall.
+ *
+ * Copyright (c) 2015-2022 Dmitry V. Levin <ldv@strace.io>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include "scno.h"
+#include "kernel_timespec.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <linux/futex.h>
+
+static const char *errstr;
+
+static long
+k_futex_waitv(const void *const waiters,
+ const unsigned int nr_futexes,
+ const unsigned int flags,
+ const void *const timeout,
+ const unsigned int clockid)
+{
+ const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
+ const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
+ const kernel_ulong_t arg1 = (uintptr_t) waiters;
+ const kernel_ulong_t arg2 = fill | nr_futexes;
+ const kernel_ulong_t arg3 = fill | flags;
+ const kernel_ulong_t arg4 = (uintptr_t) timeout;
+ const kernel_ulong_t arg5 = fill | clockid;
+ const long rc = syscall(__NR_futex_waitv,
+ arg1, arg2, arg3, arg4, arg5, bad);
+ errstr = sprintrc(rc);
+ return rc;
+}
+
+int
+main(void)
+{
+ TAIL_ALLOC_OBJECT_CONST_PTR(uint32_t, futex);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct futex_waitv, waiter);
+ TAIL_ALLOC_OBJECT_CONST_PTR(kernel_timespec64_t, ts);
+ ts->tv_sec = 1;
+ ts->tv_nsec = 2;
+
+ k_futex_waitv(0, 1, -1U, 0, 1);
+ printf("futex_waitv(NULL, 1, %#x, NULL, CLOCK_MONOTONIC) = %s\n",
+ -1U, errstr);
+
+ k_futex_waitv(waiter + 1, 0, 1, ts + 1, -1U);
+ printf("futex_waitv([], 0, %#x, %p, %#x /* CLOCK_??? */) = %s\n",
+ 1, ts + 1, -1U, errstr);
+
+ k_futex_waitv((void *) waiter + 1, 1, 0, ts, 0);
+ printf("futex_waitv(%p, 1, 0, {tv_sec=1, tv_nsec=2}, CLOCK_REALTIME)"
+ " = %s\n",
+ (void *) waiter + 1, errstr);
+
+ waiter->uaddr = 0;
+ k_futex_waitv(waiter, 1, 0, 0, 1);
+ printf("futex_waitv([{val=%#llx, uaddr=NULL, flags=%s|%#x"
+ ", __reserved=%#x}], 1, 0, NULL, CLOCK_MONOTONIC) = %s\n",
+ (unsigned long long) waiter->val,
+ "FUTEX_32|FUTEX_PRIVATE_FLAG",
+ waiter->flags & ~(FUTEX_32|FUTEX_PRIVATE_FLAG),
+ waiter->__reserved, errstr);
+
+ waiter->val = 0xdeadbeeffacefeedULL;
+ waiter->uaddr = -1ULL;
+ waiter->flags = 0;
+ waiter->__reserved = 0;
+ k_futex_waitv(waiter, 1, 0, 0, 2);
+ printf("futex_waitv([{val=%#llx, uaddr=%#llx, flags=0}], 1, 0, NULL"
+ ", CLOCK_PROCESS_CPUTIME_ID) = %s\n",
+ (unsigned long long) waiter->val,
+ (unsigned long long) waiter->uaddr,
+ errstr);
+
+ waiter->val = 0;
+ waiter->uaddr = (uintptr_t) futex;
+ waiter->flags = FUTEX_PRIVATE_FLAG;
+ k_futex_waitv(waiter, 1, 0, 0, 0);
+ printf("futex_waitv([{val=0, uaddr=%p, flags=%s}], 1, 0, NULL"
+ ", CLOCK_REALTIME) = %s\n",
+ futex, "FUTEX_PRIVATE_FLAG", errstr);
+
+ waiter->flags = FUTEX_32;
+ k_futex_waitv(waiter, 2, 0, 0, 1);
+ printf("futex_waitv([{val=0, uaddr=%p, flags=%s}, ... /* %p */], 2, 0, NULL"
+ ", CLOCK_MONOTONIC) = %s\n",
+ futex, "FUTEX_32", waiter + 1, errstr);
+
+ waiter->flags = FUTEX_32|FUTEX_PRIVATE_FLAG;
+ k_futex_waitv(waiter, 1, 0, ts, 1);
+ printf("futex_waitv([{val=0, uaddr=%p, flags=%s}], 1, 0"
+ ", {tv_sec=1, tv_nsec=2}, CLOCK_MONOTONIC) = %s\n",
+ futex, "FUTEX_32|FUTEX_PRIVATE_FLAG", errstr);
+
+ unsigned int nr = FUTEX_WAITV_MAX + 1;
+ uint32_t * const futexes = tail_alloc(nr * sizeof(*futexes));
+ struct futex_waitv * const waiters = tail_alloc(nr * sizeof(*waiters));
+ for (unsigned int i = 0; i < nr; ++i) {
+ futexes[i] = i;
+ waiters[i].val = i;
+ waiters[i].uaddr = (uintptr_t) &futexes[i];
+ waiters[i].flags = FUTEX_32|FUTEX_PRIVATE_FLAG;
+ waiters[i].__reserved = 0;
+ }
+ k_futex_waitv(waiters, nr, 0, ts, 1);
+ printf("futex_waitv([");
+ for (unsigned int i = 0; i < FUTEX_WAITV_MAX; ++i) {
+ printf("%s{val=%#x, uaddr=%p, flags=%s}",
+ i ? ", " : "",
+ i, &futexes[i], "FUTEX_32|FUTEX_PRIVATE_FLAG");
+ }
+ printf(", ...], %u, 0, {tv_sec=1, tv_nsec=2}, CLOCK_MONOTONIC) = %s\n",
+ nr, errstr);
+
+ nr = FUTEX_WAITV_MAX;
+ k_futex_waitv(waiters + 1, nr, 0, ts, 1);
+ printf("futex_waitv([");
+ for (unsigned int i = 0; i < FUTEX_WAITV_MAX; ++i) {
+ printf("%s{val=%#x, uaddr=%p, flags=%s}",
+ i ? ", " : "",
+ i + 1, &futexes[i + 1], "FUTEX_32|FUTEX_PRIVATE_FLAG");
+ }
+ printf("], %u, 0, {tv_sec=1, tv_nsec=2}, CLOCK_MONOTONIC) = %s\n",
+ nr, errstr);
+
+ puts("+++ exited with 0 +++");
+ return 0;
+}
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 8e6d9f3d7..588c06f4c 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -186,6 +186,7 @@ fsync -a10
fsync-y -y -e trace=fsync
ftruncate -a24
ftruncate64 -a36
+futex_waitv -s256
futimesat -a28
get_mempolicy -s3 -a38
getcpu -a25
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index 93aaf7239..b95bbaa1a 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -120,6 +120,7 @@ fsync
ftruncate
ftruncate64
futex
+futex_waitv
futimesat
get_mempolicy
getcpu