* [LTP] [PATCH v2 1/2] Update lapi/futex.h fallback
2022-01-19 9:13 [LTP] [PATCH v2 0/2] Add futex_wait testing suite Andrea Cervesato
@ 2022-01-19 9:13 ` Andrea Cervesato
2022-02-01 15:41 ` Cyril Hrubis
2022-01-19 9:13 ` [LTP] [PATCH v2 2/2] Add futex_waitv testing suite Andrea Cervesato
1 sibling, 1 reply; 6+ messages in thread
From: Andrea Cervesato @ 2022-01-19 9:13 UTC (permalink / raw)
To: ltp
Added a complete futex.h definition with futex2 support
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de>
---
configure.ac | 3 +
include/lapi/futex.h | 180 ++++++++++++++++++
include/lapi/syscalls/aarch64.in | 1 +
include/lapi/syscalls/arc.in | 1 +
include/lapi/syscalls/arm.in | 1 +
include/lapi/syscalls/hppa.in | 1 +
include/lapi/syscalls/i386.in | 1 +
include/lapi/syscalls/ia64.in | 1 +
include/lapi/syscalls/mips_n32.in | 1 +
include/lapi/syscalls/mips_n64.in | 1 +
include/lapi/syscalls/mips_o32.in | 1 +
include/lapi/syscalls/powerpc.in | 1 +
include/lapi/syscalls/powerpc64.in | 1 +
include/lapi/syscalls/s390.in | 1 +
include/lapi/syscalls/s390x.in | 1 +
include/lapi/syscalls/sh.in | 1 +
include/lapi/syscalls/sparc.in | 1 +
include/lapi/syscalls/sparc64.in | 1 +
include/lapi/syscalls/x86_64.in | 1 +
lib/tst_checkpoint.c | 1 -
testcases/kernel/syscalls/clone/clone08.c | 1 -
.../syscalls/futex/futex_cmp_requeue01.c | 2 +-
.../syscalls/futex/futex_cmp_requeue02.c | 2 +-
testcases/kernel/syscalls/futex/futextest.h | 72 +++----
24 files changed, 231 insertions(+), 47 deletions(-)
diff --git a/configure.ac b/configure.ac
index 3c56d1922..88afec2c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,6 +51,7 @@ AC_CHECK_HEADERS_ONCE([ \
linux/close_range.h \
linux/dccp.h \
linux/fs.h \
+ linux/futex.h \
linux/genetlink.h \
linux/if_alg.h \
linux/if_ether.h \
@@ -216,6 +217,8 @@ AC_CHECK_TYPES([struct xt_entry_match, struct xt_entry_target],,,[
AC_CHECK_TYPES([struct __kernel_old_timeval, struct __kernel_old_timespec, struct __kernel_timespec,
struct __kernel_old_itimerspec, struct __kernel_itimerspec],,,[#include <sys/socket.h>])
+AC_CHECK_TYPES([struct futex_waitv],,,[#include <linux/futex.h>])
+
# Tools knobs
# Bash
diff --git a/include/lapi/futex.h b/include/lapi/futex.h
index 00b26c355..a05fcb89c 100644
--- a/include/lapi/futex.h
+++ b/include/lapi/futex.h
@@ -1,12 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015 Linux Test Project
+ * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
#ifndef LAPI_FUTEX_H__
#define LAPI_FUTEX_H__
#include <stdint.h>
+#include "config.h"
typedef volatile uint32_t futex_t;
@@ -14,4 +16,182 @@ typedef volatile uint32_t futex_t;
#define SYS_futex SYS_futex_time64
#endif
+#ifdef HAVE_LINUX_FUTEX_H
+# include <linux/futex.h>
+#else
+#include <unistd.h>
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_FD 2
+#define FUTEX_REQUEUE 3
+#define FUTEX_CMP_REQUEUE 4
+#define FUTEX_WAKE_OP 5
+#define FUTEX_LOCK_PI 6
+#define FUTEX_UNLOCK_PI 7
+#define FUTEX_TRYLOCK_PI 8
+#define FUTEX_WAIT_BITSET 9
+#define FUTEX_WAKE_BITSET 10
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+#define FUTEX_LOCK_PI2 13
+
+#define FUTEX_PRIVATE_FLAG 128
+#define FUTEX_CLOCK_REALTIME 256
+#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
+
+#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_REQUEUE_PRIVATE (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_OP_PRIVATE (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
+#define FUTEX_LOCK_PI_PRIVATE (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_LOCK_PI2_PRIVATE (FUTEX_LOCK_PI2 | FUTEX_PRIVATE_FLAG)
+#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_BITSET_PRIVATE (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAIT_REQUEUE_PI_PRIVATE (FUTEX_WAIT_REQUEUE_PI | \
+ FUTEX_PRIVATE_FLAG)
+#define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | \
+ FUTEX_PRIVATE_FLAG)
+
+/*
+ * Support for robust futexes: the kernel cleans up held futexes at
+ * thread exit time.
+ */
+
+/*
+ * Per-lock list entry - embedded in user-space locks, somewhere close
+ * to the futex field. (Note: user-space uses a double-linked list to
+ * achieve O(1) list add and remove, but the kernel only needs to know
+ * about the forward link)
+ *
+ * NOTE: this structure is part of the syscall ABI, and must not be
+ * changed.
+ */
+struct robust_list {
+ struct robust_list *next;
+};
+
+/*
+ * Per-thread list head:
+ *
+ * NOTE: this structure is part of the syscall ABI, and must only be
+ * changed if the change is first communicated with the glibc folks.
+ * (When an incompatible change is done, we'll increase the structure
+ * size, which glibc will detect)
+ */
+struct robust_list_head {
+ /*
+ * The head of the list. Points back to itself if empty:
+ */
+ struct robust_list list;
+
+ /*
+ * This relative offset is set by user-space, it gives the kernel
+ * the relative position of the futex field to examine. This way
+ * we keep userspace flexible, to freely shape its data-structure,
+ * without hardcoding any particular offset into the kernel:
+ */
+ long futex_offset;
+
+ /*
+ * The death of the thread may race with userspace setting
+ * up a lock's links. So to handle this race, userspace first
+ * sets this field to the address of the to-be-taken lock,
+ * then does the lock acquire, and then adds itself to the
+ * list, and then clears this field. Hence the kernel will
+ * always have full knowledge of all locks that the thread
+ * _might_ have taken. We check the owner TID in any case,
+ * so only truly owned locks will be handled.
+ */
+ struct robust_list *list_op_pending;
+};
+
+/*
+ * Are there any waiters for this robust futex:
+ */
+#define FUTEX_WAITERS 0x80000000
+
+/*
+ * The kernel signals via this bit that a thread holding a futex
+ * has exited without unlocking the futex. The kernel also does
+ * a FUTEX_WAKE on such futexes, after setting the bit, to wake
+ * up any possible waiters:
+ */
+#define FUTEX_OWNER_DIED 0x40000000
+
+/*
+ * The rest of the robust-futex field is for the TID:
+ */
+#define FUTEX_TID_MASK 0x3fffffff
+
+/*
+ * This limit protects against a deliberately circular list.
+ * (Not worth introducing an rlimit for it)
+ */
+#define ROBUST_LIST_LIMIT 2048
+
+/*
+ * bitset with all bits set for the FUTEX_xxx_BITSET OPs to request a
+ * match of any bit.
+ */
+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
+
+
+#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
+#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
+#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
+#define FUTEX_OP_ANDN 3 /* *(int *)UADDR2 &= ~OPARG; */
+#define FUTEX_OP_XOR 4 /* *(int *)UADDR2 ^= OPARG; */
+
+#define FUTEX_OP_OPARG_SHIFT 8 /* Use (1 << OPARG) instead of OPARG. */
+
+#define FUTEX_OP_CMP_EQ 0 /* if (oldval == CMPARG) wake */
+#define FUTEX_OP_CMP_NE 1 /* if (oldval != CMPARG) wake */
+#define FUTEX_OP_CMP_LT 2 /* if (oldval < CMPARG) wake */
+#define FUTEX_OP_CMP_LE 3 /* if (oldval <= CMPARG) wake */
+#define FUTEX_OP_CMP_GT 4 /* if (oldval > CMPARG) wake */
+#define FUTEX_OP_CMP_GE 5 /* if (oldval >= CMPARG) wake */
+
+/* FUTEX_WAKE_OP will perform atomically
+ int oldval = *(int *)UADDR2;
+ *(int *)UADDR2 = oldval OP OPARG;
+ if (oldval CMP CMPARG)
+ wake UADDR2; */
+
+#define FUTEX_OP(op, oparg, cmp, cmparg) \
+ (((op & 0xf) << 28) | ((cmp & 0xf) << 24) \
+ | ((oparg & 0xfff) << 12) | (cmparg & 0xfff))
+
+#endif /* HAVE_LINUX_FUTEX_H */
+
+#ifndef HAVE_STRUCT_FUTEX_WAITV
+/*
+ * Flags to specify the bit length of the futex word for futex2 syscalls.
+ * Currently, only 32 is supported.
+ */
+#define FUTEX_32 2
+
+/*
+ * Max numbers of elements in a futex_waitv array
+ */
+#define FUTEX_WAITV_MAX 128
+
+/**
+ * struct futex_waitv - A waiter for vectorized wait
+ * @val: Expected value at uaddr
+ * @uaddr: User address to wait on
+ * @flags: Flags for this waiter
+ * @__reserved: Reserved member to preserve data alignment. Should be 0.
+ */
+struct futex_waitv {
+ uint64_t val;
+ uint64_t uaddr;
+ uint32_t flags;
+ uint32_t __reserved;
+};
+#endif /* HAVE_STRUCT_FUTEX_WAITV */
+
#endif /* LAPI_FUTEX_H__ */
diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
index 89b63ee4b..de4ed5fb1 100644
--- a/include/lapi/syscalls/aarch64.in
+++ b/include/lapi/syscalls/aarch64.in
@@ -295,4 +295,5 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
_sysctl 1078
diff --git a/include/lapi/syscalls/arc.in b/include/lapi/syscalls/arc.in
index 72420754a..9f11381db 100644
--- a/include/lapi/syscalls/arc.in
+++ b/include/lapi/syscalls/arc.in
@@ -315,3 +315,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
index 2a78d7c3c..4b0f63a28 100644
--- a/include/lapi/syscalls/arm.in
+++ b/include/lapi/syscalls/arm.in
@@ -393,3 +393,4 @@ openat2 (__NR_SYSCALL_BASE+437)
pidfd_getfd (__NR_SYSCALL_BASE+438)
epoll_pwait2 (__NR_SYSCALL_BASE+441)
quotactl_fd (__NR_SYSCALL_BASE+443)
+futex_waitv (__NR_SYSCALL_BASE+449)
diff --git a/include/lapi/syscalls/hppa.in b/include/lapi/syscalls/hppa.in
index 2f0fc8153..b6d32d386 100644
--- a/include/lapi/syscalls/hppa.in
+++ b/include/lapi/syscalls/hppa.in
@@ -42,3 +42,4 @@ pidfd_open 434
close_range 436
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
index 34a8a621f..d0e6e9a4b 100644
--- a/include/lapi/syscalls/i386.in
+++ b/include/lapi/syscalls/i386.in
@@ -429,3 +429,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
index b729cd3f0..123200624 100644
--- a/include/lapi/syscalls/ia64.in
+++ b/include/lapi/syscalls/ia64.in
@@ -342,3 +342,4 @@ openat2 1461
pidfd_getfd 1462
epoll_pwait2 1465
quotactl_fd 1467
+futex_waitv 1473
diff --git a/include/lapi/syscalls/mips_n32.in b/include/lapi/syscalls/mips_n32.in
index 46098a616..e818c9d92 100644
--- a/include/lapi/syscalls/mips_n32.in
+++ b/include/lapi/syscalls/mips_n32.in
@@ -370,3 +370,4 @@ process_madvise 6440
epoll_pwait2 6441
mount_setattr 6442
quotactl_fd 6443
+futex_waitv 6449
diff --git a/include/lapi/syscalls/mips_n64.in b/include/lapi/syscalls/mips_n64.in
index 07f96ac5d..6e15f43b3 100644
--- a/include/lapi/syscalls/mips_n64.in
+++ b/include/lapi/syscalls/mips_n64.in
@@ -346,3 +346,4 @@ process_madvise 5440
epoll_pwait2 5441
mount_setattr 5442
quotactl_fd 5443
+futex_waitv 5449
diff --git a/include/lapi/syscalls/mips_o32.in b/include/lapi/syscalls/mips_o32.in
index 5e64a4a1c..921d5d331 100644
--- a/include/lapi/syscalls/mips_o32.in
+++ b/include/lapi/syscalls/mips_o32.in
@@ -416,3 +416,4 @@ process_madvise 4440
epoll_pwait2 4441
mount_setattr 4442
quotactl_fd 4443
+futex_waitv 4449
diff --git a/include/lapi/syscalls/powerpc.in b/include/lapi/syscalls/powerpc.in
index f4e85940c..d5de621e1 100644
--- a/include/lapi/syscalls/powerpc.in
+++ b/include/lapi/syscalls/powerpc.in
@@ -422,3 +422,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
index f4e85940c..d5de621e1 100644
--- a/include/lapi/syscalls/powerpc64.in
+++ b/include/lapi/syscalls/powerpc64.in
@@ -422,3 +422,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
index 3e16d8475..6505f3822 100644
--- a/include/lapi/syscalls/s390.in
+++ b/include/lapi/syscalls/s390.in
@@ -409,3 +409,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
index beb0819af..bc5d2b34c 100644
--- a/include/lapi/syscalls/s390x.in
+++ b/include/lapi/syscalls/s390x.in
@@ -357,3 +357,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
index a81cf8297..316ffe5f1 100644
--- a/include/lapi/syscalls/sh.in
+++ b/include/lapi/syscalls/sh.in
@@ -403,3 +403,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
index 6a7817ae5..e0c60a360 100644
--- a/include/lapi/syscalls/sparc.in
+++ b/include/lapi/syscalls/sparc.in
@@ -408,3 +408,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/sparc64.in b/include/lapi/syscalls/sparc64.in
index d3995181c..0acde6856 100644
--- a/include/lapi/syscalls/sparc64.in
+++ b/include/lapi/syscalls/sparc64.in
@@ -373,3 +373,4 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
index a5b2a24fe..1863e1df7 100644
--- a/include/lapi/syscalls/x86_64.in
+++ b/include/lapi/syscalls/x86_64.in
@@ -350,6 +350,7 @@ openat2 437
pidfd_getfd 438
epoll_pwait2 441
quotactl_fd 443
+futex_waitv 449
rt_sigaction 512
rt_sigreturn 513
ioctl 514
diff --git a/lib/tst_checkpoint.c b/lib/tst_checkpoint.c
index b41986f0c..6a294b28b 100644
--- a/lib/tst_checkpoint.c
+++ b/lib/tst_checkpoint.c
@@ -25,7 +25,6 @@
#include <limits.h>
#include <errno.h>
#include <sys/syscall.h>
-#include <linux/futex.h>
#include "test.h"
#include "safe_macros.h"
diff --git a/testcases/kernel/syscalls/clone/clone08.c b/testcases/kernel/syscalls/clone/clone08.c
index 3de1fe9bb..ad285a497 100644
--- a/testcases/kernel/syscalls/clone/clone08.c
+++ b/testcases/kernel/syscalls/clone/clone08.c
@@ -11,7 +11,6 @@
#include <errno.h>
#include <sched.h>
#include <sys/wait.h>
-#include <linux/futex.h>
#include "tst_test.h"
#include "clone_platform.h"
diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c
index 13e67c758..bef44838e 100644
--- a/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c
+++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue01.c
@@ -12,12 +12,12 @@
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
-#include <linux/futex.h>
#include <sys/time.h>
#include "tst_timer_test.h"
#include "tst_test.h"
#include "futextest.h"
+#include "lapi/futex.h"
struct shared_data {
futex_t futexes[2];
diff --git a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
index 0514b0ba4..073ea3bf6 100644
--- a/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
+++ b/testcases/kernel/syscalls/futex/futex_cmp_requeue02.c
@@ -13,11 +13,11 @@
*/
#include <errno.h>
-#include <linux/futex.h>
#include <sys/time.h>
#include "tst_test.h"
#include "futextest.h"
+#include "lapi/futex.h"
static futex_t *futexes;
diff --git a/testcases/kernel/syscalls/futex/futextest.h b/testcases/kernel/syscalls/futex/futextest.h
index 3f2f36fef..da5f61767 100644
--- a/testcases/kernel/syscalls/futex/futextest.h
+++ b/testcases/kernel/syscalls/futex/futextest.h
@@ -14,54 +14,15 @@
#define _FUTEXTEST_H
#include <unistd.h>
-#include <sys/syscall.h>
+#include <time.h>
#include <sys/types.h>
-#include <linux/futex.h>
-#include "lapi/futex.h"
+#include "tst_test.h"
#include "tst_timer.h"
+#include "lapi/futex.h"
+#include "lapi/syscalls.h"
#define FUTEX_INITIALIZER 0
-#ifndef FUTEX_CMP_REQUEUE
-# define FUTEX_CMP_REQUEUE 4
-#endif
-#ifndef FUTEX_WAKE_OP
-# define FUTEX_WAKE_OP 5
-#endif
-#ifndef FUTEX_LOCK_PI
-# define FUTEX_LOCK_PI 6
-#endif
-#ifndef FUTEX_UNLOCK_PI
-# define FUTEX_UNLOCK_PI 7
-#endif
-#ifndef FUTEX_WAIT_BITSET
-# define FUTEX_WAIT_BITSET 9
-#endif
-#ifndef FUTEX_WAKE_BITSET
-# define FUTEX_WAKE_BITSET 10
-#endif
-#ifndef FUTEX_WAIT_REQUEUE_PI
-# define FUTEX_WAIT_REQUEUE_PI 11
-#endif
-#ifndef FUTEX_CMP_REQUEUE_PI
-# define FUTEX_CMP_REQUEUE_PI 12
-#endif
-#ifndef FUTEX_PRIVATE_FLAG
-# define FUTEX_PRIVATE_FLAG 128
-#endif
-#ifndef FUTEX_WAIT_REQUEUE_PI_PRIVATE
-# define FUTEX_WAIT_REQUEUE_PI_PRIVATE (FUTEX_WAIT_REQUEUE_PI | \
- FUTEX_PRIVATE_FLAG)
-#endif
-#ifndef FUTEX_REQUEUE_PI_PRIVATE
-# define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | \
- FUTEX_PRIVATE_FLAG)
-#endif
-
-#ifndef FUTEX_CLOCK_REALTIME
-# define FUTEX_CLOCK_REALTIME 256
-#endif
-
enum futex_fn_type {
FUTEX_FN_FUTEX,
FUTEX_FN_FUTEX64,
@@ -74,6 +35,16 @@ struct futex_test_variants {
char *desc;
};
+struct futex_test_variants futex_variants[] = {
+#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec" },
+#endif
+
+#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
+ { .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec" },
+#endif
+};
+
static inline void futex_supported_by_kernel(enum futex_fn_type fntype)
{
if (fntype != FUTEX_FN_FUTEX64)
@@ -318,4 +289,19 @@ futex_set(futex_t *uaddr, u_int32_t newval)
return newval;
}
+/**
+ * futex_waitv - Wait at multiple futexes, wake on any
+ * @waiters: Array of waiters
+ * @nr_waiters: Length of waiters array
+ * @flags: Operation flags
+ * @timo: Optional timeout for operation
+ */
+static inline int
+tst_futex_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters,
+ unsigned long flags, struct timespec *timo, clockid_t clockid)
+{
+ return tst_syscall(__NR_futex_waitv,
+ waiters, nr_waiters, flags, timo, clockid);
+}
+
#endif
--
2.34.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 6+ messages in thread* [LTP] [PATCH v2 2/2] Add futex_waitv testing suite
2022-01-19 9:13 [LTP] [PATCH v2 0/2] Add futex_wait testing suite Andrea Cervesato
2022-01-19 9:13 ` [LTP] [PATCH v2 1/2] Update lapi/futex.h fallback Andrea Cervesato
@ 2022-01-19 9:13 ` Andrea Cervesato
2022-02-02 10:06 ` Cyril Hrubis
1 sibling, 1 reply; 6+ messages in thread
From: Andrea Cervesato @ 2022-01-19 9:13 UTC (permalink / raw)
To: ltp
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de>
---
testcases/kernel/syscalls/futex/.gitignore | 3 +
testcases/kernel/syscalls/futex/Makefile | 14 +-
.../kernel/syscalls/futex/futex_waitv01.c | 129 ++++++++++++++++++
.../kernel/syscalls/futex/futex_waitv02.c | 104 ++++++++++++++
.../kernel/syscalls/futex/futex_waitv03.c | 112 +++++++++++++++
5 files changed, 360 insertions(+), 2 deletions(-)
create mode 100644 testcases/kernel/syscalls/futex/futex_waitv01.c
create mode 100644 testcases/kernel/syscalls/futex/futex_waitv02.c
create mode 100644 testcases/kernel/syscalls/futex/futex_waitv03.c
diff --git a/testcases/kernel/syscalls/futex/.gitignore b/testcases/kernel/syscalls/futex/.gitignore
index 54cd02b02..9d08ba7d3 100644
--- a/testcases/kernel/syscalls/futex/.gitignore
+++ b/testcases/kernel/syscalls/futex/.gitignore
@@ -10,3 +10,6 @@
/futex_wake02
/futex_wake03
/futex_wake04
+/futex_waitv01
+/futex_waitv02
+/futex_waitv03
diff --git a/testcases/kernel/syscalls/futex/Makefile b/testcases/kernel/syscalls/futex/Makefile
index 5713c615d..7228496bc 100644
--- a/testcases/kernel/syscalls/futex/Makefile
+++ b/testcases/kernel/syscalls/futex/Makefile
@@ -3,8 +3,18 @@
top_srcdir ?= ../../../..
-futex_cmp_requeue01 futex_cmp_requeue02 futex_wait02 futex_wake03 futex_wait05 futex_wait_bitset01: LDLIBS += -lrt
-futex_wait03 futex_wake02 futex_wake04: CFLAGS += -pthread
+futex_cmp_requeue01: LDLIBS+=-lrt
+futex_cmp_requeue02: LDLIBS+=-lrt
+futex_wait02: LDLIBS+=-lrt
+futex_wake03: LDLIBS+=-lrt
+futex_wait05: LDLIBS+=-lrt
+futex_wait_bitset01: LDLIBS+=-lrt
+
+futex_wait03: CFLAGS+=-pthread
+futex_wake02: CFLAGS+=-pthread
+futex_wake04: CFLAGS+=-pthread
+futex_waitv02: CFLAGS+=-pthread
+futex_waitv03: CFLAGS+=-pthread
include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/futex/futex_waitv01.c b/testcases/kernel/syscalls/futex/futex_waitv01.c
new file mode 100644
index 000000000..ccf1699de
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_waitv01.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test verifies EINVAL for futex_waitv syscall.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include "tst_test.h"
+#include "futextest.h"
+
+static char *str_numfutex;
+static int numfutex = 30;
+
+static uint32_t *futexes;
+static struct futex_waitv *waitv;
+
+static void setup(void)
+{
+ struct futex_test_variants tv;
+ int i;
+
+ tv = futex_variants[tst_variant];
+
+ tst_res(TINFO, "Testing variant: %s", tv.desc);
+ futex_supported_by_kernel(tv.fntype);
+
+ if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
+ tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
+
+ futexes = SAFE_MALLOC(sizeof(uint32_t) * numfutex);
+ memset(futexes, 0, numfutex);
+
+ waitv = SAFE_MALLOC(sizeof(struct futex_waitv) * numfutex);
+ for (i = 0; i < numfutex; i++) {
+ waitv[i].uaddr = (uintptr_t)&futexes[i];
+ waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
+ waitv[i].val = 0;
+ }
+}
+
+static void cleanup(void)
+{
+ free(futexes);
+ free(waitv);
+}
+
+static void init_timeout(struct timespec *to)
+{
+ if (clock_gettime(CLOCK_MONOTONIC, to))
+ tst_brk(TBROK, "gettime64 failed");
+
+ to->tv_sec++;
+}
+
+static void run(void)
+{
+ struct timespec to;
+ int res;
+
+ /* Testing a waiter without FUTEX_32 flag */
+ waitv[0].flags = FUTEX_PRIVATE_FLAG;
+
+ init_timeout(&to);
+
+ res = tst_futex_waitv(waitv, numfutex, 0, &to, CLOCK_MONOTONIC);
+ if (res == EINVAL)
+ tst_res(TFAIL, "futex_waitv private returned: %d %s", res, tst_strerrno(res));
+ else
+ tst_res(TPASS, "futex_waitv without FUTEX_32");
+
+ /* Testing a waiter with an unaligned address */
+ waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32;
+ waitv[0].uaddr = 1;
+
+ init_timeout(&to);
+
+ res = tst_futex_waitv(waitv, numfutex, 0, &to, CLOCK_MONOTONIC);
+ if (res == EINVAL)
+ tst_res(TFAIL, "futex_waitv private returned: %d %s", res, tst_strerrno(res));
+ else
+ tst_res(TPASS, "futex_waitv with an unaligned address");
+
+ /* Testing a NULL address for waiters.uaddr */
+ waitv[0].uaddr = 0x00000000;
+
+ init_timeout(&to);
+
+ res = tst_futex_waitv(waitv, numfutex, 0, &to, CLOCK_MONOTONIC);
+ if (res == EINVAL)
+ tst_res(TFAIL, "futex_waitv private returned: %d %s", res, tst_strerrno(res));
+ else
+ tst_res(TPASS, "futex_waitv NULL address in waitv.uaddr");
+
+ /* Testing a NULL address for *waiters */
+ init_timeout(&to);
+
+ res = tst_futex_waitv(NULL, numfutex, 0, &to, CLOCK_MONOTONIC);
+ if (res == EINVAL)
+ tst_res(TFAIL, "futex_waitv private returned: %d %s", res, tst_strerrno(res));
+ else
+ tst_res(TPASS, "futex_waitv NULL address in *waiters");
+
+ /* Testing an invalid clockid */
+ init_timeout(&to);
+
+ res = tst_futex_waitv(NULL, numfutex, 0, &to, CLOCK_TAI);
+ if (res == EINVAL)
+ tst_res(TFAIL, "futex_waitv private returned: %d %s", res, tst_strerrno(res));
+ else
+ tst_res(TPASS, "futex_waitv invalid clockid");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "5.16",
+ .test_variants = ARRAY_SIZE(futex_variants),
+ .options = (struct tst_option[]){
+ {"n:", &str_numfutex, "Number of futex (default 30)"},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/futex/futex_waitv02.c b/testcases/kernel/syscalls/futex/futex_waitv02.c
new file mode 100644
index 000000000..a19568993
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_waitv02.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test verifies futex_waitv syscall using private data.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include "tst_test.h"
+#include "tst_safe_pthread.h"
+#include "futextest.h"
+
+static char *str_numfutex;
+static int numfutex = 30;
+
+static uint32_t *futexes;
+static struct futex_waitv *waitv;
+
+static void setup(void)
+{
+ struct futex_test_variants tv;
+ int i;
+
+ tv = futex_variants[tst_variant];
+
+ tst_res(TINFO, "Testing variant: %s", tv.desc);
+ futex_supported_by_kernel(tv.fntype);
+
+ if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
+ tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
+
+ futexes = SAFE_MALLOC(sizeof(uint32_t) * numfutex);
+ memset(futexes, 0, numfutex);
+
+ waitv = SAFE_MALLOC(sizeof(struct futex_waitv) * numfutex);
+ for (i = 0; i < numfutex; i++) {
+ waitv[i].uaddr = (uintptr_t)&futexes[i];
+ waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
+ waitv[i].val = 0;
+ }
+}
+
+static void cleanup(void)
+{
+ free(futexes);
+ free(waitv);
+}
+
+static void *threaded(void *arg)
+{
+ struct futex_test_variants tv;
+ int ret, pid = *(int *)arg;
+
+ tv = futex_variants[tst_variant];
+
+ TST_PROCESS_STATE_WAIT(pid, 'S', 0);
+
+ ret = futex_wake(tv.fntype, (void *)(uintptr_t)waitv[numfutex - 1].uaddr, 1, FUTEX_PRIVATE_FLAG);
+ if (ret < 0)
+ tst_brk(TBROK, "futex_wake private returned: %d %s", ret, tst_strerrno(-ret));
+
+ return NULL;
+}
+
+static void run(void)
+{
+ struct timespec to;
+ int ret, pid = getpid();
+ pthread_t t;
+
+ SAFE_PTHREAD_CREATE(&t, NULL, threaded, (void *)&pid);
+
+ /* setting absolute timeout for futex2 */
+ if (clock_gettime(CLOCK_MONOTONIC, &to))
+ tst_brk(TBROK, "gettime64 failed");
+
+ to.tv_sec++;
+
+ ret = tst_futex_waitv(waitv, numfutex, 0, &to, CLOCK_MONOTONIC);
+ if (ret < 0)
+ tst_brk(TBROK, "futex_waitv returned: %d %s", ret, tst_strerrno(-ret));
+ else if (ret != numfutex - 1)
+ tst_res(TFAIL, "futex_waitv returned: %d, expecting %d", ret, numfutex - 1);
+
+ SAFE_PTHREAD_JOIN(t, NULL);
+ tst_res(TPASS, "futex_waitv returned correctly");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "5.16",
+ .test_variants = ARRAY_SIZE(futex_variants),
+ .options = (struct tst_option[]){
+ {"n:", &str_numfutex, "Number of futex (default 30)"},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/futex/futex_waitv03.c b/testcases/kernel/syscalls/futex/futex_waitv03.c
new file mode 100644
index 000000000..3f18a15a2
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_waitv03.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test verifies futex_waitv syscall using shared data.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <sys/shm.h>
+#include "tst_test.h"
+#include "tst_safe_pthread.h"
+#include "futextest.h"
+
+static char *str_numfutex;
+static int numfutex = 30;
+
+static struct futex_waitv *waitv;
+
+static void setup(void)
+{
+ struct futex_test_variants tv;
+ int shm_id;
+ int i;
+
+ tv = futex_variants[tst_variant];
+
+ tst_res(TINFO, "Testing variant: %s", tv.desc);
+ futex_supported_by_kernel(tv.fntype);
+
+ if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
+ tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
+
+ waitv = SAFE_MALLOC(sizeof(struct futex_waitv) * numfutex);
+ for (i = 0; i < numfutex; i++) {
+ shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
+ if (shm_id < 0)
+ tst_brk(TBROK, "shmget");
+
+ unsigned int *shared_data = shmat(shm_id, NULL, 0);
+
+ waitv[i].uaddr = (uintptr_t)shared_data;
+ waitv[i].flags = FUTEX_32;
+ waitv[i].val = 0;
+ }
+}
+
+static void cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < numfutex; i++)
+ shmdt((void *)(uintptr_t)waitv[i].uaddr);
+
+ free(waitv);
+}
+
+static void *threaded(void *arg)
+{
+ struct futex_test_variants tv;
+ int ret, pid = *(int *)arg;
+
+ tv = futex_variants[tst_variant];
+
+ TST_PROCESS_STATE_WAIT(pid, 'S', 0);
+
+ ret = futex_wake(tv.fntype, (void *)(uintptr_t)waitv[numfutex - 1].uaddr, 1, 0);
+ if (ret < 0)
+ tst_brk(TBROK, "futex_wake private returned: %d %s", ret, tst_strerrno(-ret));
+
+ return NULL;
+}
+
+static void run(void)
+{
+ struct timespec to;
+ int ret, pid = getpid();
+ pthread_t t;
+
+ SAFE_PTHREAD_CREATE(&t, NULL, threaded, (void *)&pid);
+
+ /* setting absolute timeout for futex2 */
+ if (clock_gettime(CLOCK_MONOTONIC, &to))
+ tst_brk(TBROK, "gettime64 failed");
+
+ to.tv_sec++;
+
+ ret = tst_futex_waitv(waitv, numfutex, 0, &to, CLOCK_MONOTONIC);
+ if (ret < 0)
+ tst_brk(TBROK, "futex_waitv returned: %d %s", ret, tst_strerrno(-ret));
+ else if (ret != numfutex - 1)
+ tst_res(TFAIL, "futex_waitv returned: %d, expecting %d", ret, numfutex - 1);
+
+ SAFE_PTHREAD_JOIN(t, NULL);
+ tst_res(TPASS, "futex_waitv returned correctly");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "5.16",
+ .test_variants = ARRAY_SIZE(futex_variants),
+ .options = (struct tst_option[]){
+ {"n:", &str_numfutex, "Number of futex (default 30)"},
+ {},
+ },
+};
--
2.34.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 6+ messages in thread