All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v2 0/2] Add futex_wait testing suite
@ 2022-01-19  9:13 Andrea Cervesato
  2022-01-19  9:13 ` [LTP] [PATCH v2 1/2] Update lapi/futex.h fallback Andrea Cervesato
  2022-01-19  9:13 ` [LTP] [PATCH v2 2/2] Add futex_waitv testing suite Andrea Cervesato
  0 siblings, 2 replies; 6+ messages in thread
From: Andrea Cervesato @ 2022-01-19  9:13 UTC (permalink / raw)
  To: ltp

futex_waitv tests have been inspired by
tools/testing/selftests/futex/functional/futex_waitv.c that can be found
in the Linux kernel official repository.

Andrea Cervesato (2):
  Update lapi/futex.h fallback
  Add futex_waitv testing suite

 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 -
 testcases/kernel/syscalls/futex/.gitignore    |   3 +
 testcases/kernel/syscalls/futex/Makefile      |  14 +-
 .../syscalls/futex/futex_cmp_requeue01.c      |   2 +-
 .../syscalls/futex/futex_cmp_requeue02.c      |   2 +-
 .../kernel/syscalls/futex/futex_waitv01.c     | 129 +++++++++++++
 .../kernel/syscalls/futex/futex_waitv02.c     | 104 ++++++++++
 .../kernel/syscalls/futex/futex_waitv03.c     | 112 +++++++++++
 testcases/kernel/syscalls/futex/futextest.h   |  72 +++----
 29 files changed, 591 insertions(+), 49 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

-- 
2.34.1


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [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

* Re: [LTP] [PATCH v2 1/2] Update lapi/futex.h fallback
  2022-01-19  9:13 ` [LTP] [PATCH v2 1/2] Update lapi/futex.h fallback Andrea Cervesato
@ 2022-02-01 15:41   ` Cyril Hrubis
  2022-02-02  6:47     ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 6+ messages in thread
From: Cyril Hrubis @ 2022-02-01 15:41 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> +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
> +};

I guess that there should be a followup patch that makse use of this in
all the futex tests, right?

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [LTP] [PATCH v2 1/2] Update lapi/futex.h fallback
  2022-02-01 15:41   ` Cyril Hrubis
@ 2022-02-02  6:47     ` Andrea Cervesato via ltp
  0 siblings, 0 replies; 6+ messages in thread
From: Andrea Cervesato via ltp @ 2022-02-02  6:47 UTC (permalink / raw)
  To: Cyril Hrubis, Andrea Cervesato; +Cc: ltp


[-- Attachment #1.1: Type: text/plain, Size: 642 bytes --]

Hi,

yes that's the idea. The issue now is that imports are bad sorted after 
tst_syscall patch and I need to create a v3. Gonna send it

Andrea

On 2/1/22 16:41, Cyril Hrubis wrote:
> Hi!
>> +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
>> +};
> I guess that there should be a followup patch that makse use of this in
> all the futex tests, right?
>

[-- Attachment #1.2: Type: text/html, Size: 1195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 60 bytes --]


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [LTP] [PATCH v2 2/2] Add futex_waitv testing suite
  2022-01-19  9:13 ` [LTP] [PATCH v2 2/2] Add futex_waitv testing suite Andrea Cervesato
@ 2022-02-02 10:06   ` Cyril Hrubis
  0 siblings, 0 replies; 6+ messages in thread
From: Cyril Hrubis @ 2022-02-02 10:06 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> 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;
> +	}

Can we allocate these data structures with the guarded buffers?

https://github.com/linux-test-project/ltp/wiki/C-Test-API#131-guarded-buffers

> +}
> +
> +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");

SAFE_CLOCK_GETTIME()

> +	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");

Can we put these testcases into a tcase structure as we usually do in
tests?

> +}
> +
> +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)"},

I'm not sure if it makes that much sense to add the number of futexes to
this test.

> +		{},
> +	},
> +};
> 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;
> +	}

Here as well, guarded buffers please.

> +}
> +
> +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);

Hmm I guess that this works because the original thread that executes
the run() function is the one whose status is exported in the
/proc/$PID/stat file.

Technically there is no need to pass the pid like this since all threads
would have the same pid. What they differ in is the tid (there is no
difference in tid and pid from the kernel point of view though).

I guess that it would be cleaner though to add TST_THREAD_STATE_WAIT()
that would look exactly the same as TST_PROCESS_STATE_WAIT() but would
operate on the tid (see gettid()) and would open
/proc/self/task/$TID/stat instead of /proc/$PID/stat. That way we
could wait on any thread, not only the first one the program had started
with.

> +	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");

SAFE_CLOCK_GETTIME()

> +	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

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-02-02 10:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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-02-01 15:41   ` Cyril Hrubis
2022-02-02  6:47     ` Andrea Cervesato via ltp
2022-01-19  9:13 ` [LTP] [PATCH v2 2/2] Add futex_waitv testing suite Andrea Cervesato
2022-02-02 10:06   ` Cyril Hrubis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.