All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v4 0/3] Add futex_wait testing suite
@ 2022-02-07 14:41 Andrea Cervesato
  2022-02-07 14:41 ` [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro Andrea Cervesato
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Andrea Cervesato @ 2022-02-07 14:41 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 (3):
  Add TST_THREAD_STATE_WAIT macro
  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 +
 include/tst_test.h                            |   1 +
 include/tst_thread_state.h                    |  33 ++++
 lib/tst_checkpoint.c                          |   1 -
 lib/tst_thread_state.c                        |  37 ++++
 testcases/kernel/syscalls/clone/clone08.c     |   1 -
 testcases/kernel/syscalls/futex/.gitignore    |   3 +
 testcases/kernel/syscalls/futex/Makefile      |  14 +-
 testcases/kernel/syscalls/futex/futex2test.h  |  30 +++
 .../syscalls/futex/futex_cmp_requeue01.c      |   2 +-
 .../syscalls/futex/futex_cmp_requeue02.c      |   2 +-
 .../kernel/syscalls/futex/futex_waitv01.c     | 162 ++++++++++++++++
 .../kernel/syscalls/futex/futex_waitv02.c     | 111 +++++++++++
 .../kernel/syscalls/futex/futex_waitv03.c     | 122 ++++++++++++
 testcases/kernel/syscalls/futex/futextest.h   |  58 ++----
 33 files changed, 729 insertions(+), 48 deletions(-)
 create mode 100644 include/tst_thread_state.h
 create mode 100644 lib/tst_thread_state.c
 create mode 100644 testcases/kernel/syscalls/futex/futex2test.h
 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] 8+ messages in thread

* [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro
  2022-02-07 14:41 [LTP] [PATCH v4 0/3] Add futex_wait testing suite Andrea Cervesato
@ 2022-02-07 14:41 ` Andrea Cervesato
  2022-02-08 11:09   ` Cyril Hrubis
  2022-02-07 14:41 ` [LTP] [PATCH v4 2/3] Update lapi/futex.h fallback Andrea Cervesato
  2022-02-07 14:41 ` [LTP] [PATCH v4 3/3] Add futex_waitv testing suite Andrea Cervesato
  2 siblings, 1 reply; 8+ messages in thread
From: Andrea Cervesato @ 2022-02-07 14:41 UTC (permalink / raw)
  To: ltp

The TST_THREAD_STATE_WAIT macro can be used to wait and check for
pthread state changes.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de>
---
 include/tst_test.h         |  1 +
 include/tst_thread_state.h | 33 +++++++++++++++++++++++++++++++++
 lib/tst_thread_state.c     | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 include/tst_thread_state.h
 create mode 100644 lib/tst_thread_state.c

diff --git a/include/tst_test.h b/include/tst_test.h
index 450ddf086..79067f3bf 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -27,6 +27,7 @@
 #include "tst_cmd.h"
 #include "tst_cpu.h"
 #include "tst_process_state.h"
+#include "tst_thread_state.h"
 #include "tst_atomic.h"
 #include "tst_kvercmp.h"
 #include "tst_kernel.h"
diff --git a/include/tst_thread_state.h b/include/tst_thread_state.h
new file mode 100644
index 000000000..4d6a345b8
--- /dev/null
+++ b/include/tst_thread_state.h
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*
+ * These functions helps you wait till a thread with given tpid changes state.
+ */
+
+#ifndef TST_THREAD_STATE__
+#define TST_THREAD_STATE__
+
+#include <unistd.h>
+
+/*
+ * Waits for thread state change.
+ *
+ * The state is one of the following:
+ *
+ * R - running
+ * S - sleeping
+ * D - disk sleep
+ * T - stopped
+ * t - tracing stopped
+ * Z - zombie
+ * X - dead
+ */
+#define TST_THREAD_STATE_WAIT(tid, state, msec_timeout) \
+	tst_thread_state_wait((tid), (state), (msec_timeout))
+
+int tst_thread_state_wait(pid_t tid, const char state, unsigned int msec_timeout);
+
+#endif /* TST_THREAD_STATE__ */
diff --git a/lib/tst_thread_state.c b/lib/tst_thread_state.c
new file mode 100644
index 000000000..f5580c39e
--- /dev/null
+++ b/lib/tst_thread_state.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "tst_safe_file_ops.h"
+#include "tst_thread_state.h"
+
+int tst_thread_state_wait(pid_t tid, const char state, unsigned int msec_timeout)
+{
+	char proc_path[128], cur_state;
+	unsigned int msecs = 0;
+
+	snprintf(proc_path, sizeof(proc_path), "/proc/self/task/%i/stat", tid);
+
+	for (;;) {
+		SAFE_FILE_SCANF(proc_path, "%*i %*s %c", &cur_state);
+
+		if (state == cur_state)
+			break;
+
+		usleep(1000);
+		msecs += 1;
+
+		if (msec_timeout && msecs >= msec_timeout) {
+			errno = ETIMEDOUT;
+			return -1;
+		}
+	}
+
+	return 0;
+}
-- 
2.34.1


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

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

* [LTP] [PATCH v4 2/3] Update lapi/futex.h fallback
  2022-02-07 14:41 [LTP] [PATCH v4 0/3] Add futex_wait testing suite Andrea Cervesato
  2022-02-07 14:41 ` [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro Andrea Cervesato
@ 2022-02-07 14:41 ` Andrea Cervesato
  2022-02-07 14:41 ` [LTP] [PATCH v4 3/3] Add futex_waitv testing suite Andrea Cervesato
  2 siblings, 0 replies; 8+ messages in thread
From: Andrea Cervesato @ 2022-02-07 14:41 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 +-
 23 files changed, 202 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index aeb486f69..b4a8427d0 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;
 
-- 
2.34.1


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

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

* [LTP] [PATCH v4 3/3] Add futex_waitv testing suite
  2022-02-07 14:41 [LTP] [PATCH v4 0/3] Add futex_wait testing suite Andrea Cervesato
  2022-02-07 14:41 ` [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro Andrea Cervesato
  2022-02-07 14:41 ` [LTP] [PATCH v4 2/3] Update lapi/futex.h fallback Andrea Cervesato
@ 2022-02-07 14:41 ` Andrea Cervesato
  2022-02-08 11:49   ` Cyril Hrubis
  2 siblings, 1 reply; 8+ messages in thread
From: Andrea Cervesato @ 2022-02-07 14:41 UTC (permalink / raw)
  To: ltp

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de>
---
v4 introduces guarded buffers, more safe macros and TST_THREAD_STATE_WAIT usage.

 testcases/kernel/syscalls/futex/.gitignore    |   3 +
 testcases/kernel/syscalls/futex/Makefile      |  14 +-
 testcases/kernel/syscalls/futex/futex2test.h  |  30 ++++
 .../kernel/syscalls/futex/futex_waitv01.c     | 162 ++++++++++++++++++
 .../kernel/syscalls/futex/futex_waitv02.c     | 111 ++++++++++++
 .../kernel/syscalls/futex/futex_waitv03.c     | 122 +++++++++++++
 testcases/kernel/syscalls/futex/futextest.h   |  58 ++-----
 7 files changed, 456 insertions(+), 44 deletions(-)
 create mode 100644 testcases/kernel/syscalls/futex/futex2test.h
 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/futex2test.h b/testcases/kernel/syscalls/futex/futex2test.h
new file mode 100644
index 000000000..ec3667376
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex2test.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Futex2 library addons for futex tests
+ *
+ * Copyright 2021 Collabora Ltd.
+ * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+#ifndef _FUTEX2TEST_H
+#define _FUTEX2TEST_H
+
+#include <stdint.h>
+#include "lapi/syscalls.h"
+#include "futextest.h"
+
+/**
+ * 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 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 /* _FUTEX2TEST_H */
\ No newline at end of file
diff --git a/testcases/kernel/syscalls/futex/futex_waitv01.c b/testcases/kernel/syscalls/futex/futex_waitv01.c
new file mode 100644
index 000000000..928740c2f
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_waitv01.c
@@ -0,0 +1,162 @@
+// 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 <time.h>
+#include "tst_test.h"
+#include "lapi/futex.h"
+#include "futex2test.h"
+#include "tst_safe_clocks.h"
+
+static uint32_t *futex;
+static struct futex_waitv *waitv;
+
+static void setup(void)
+{
+	struct futex_test_variants tv;
+
+	tv = futex_variants();
+
+	tst_res(TINFO, "Testing variant: %s", tv.desc);
+	futex_supported_by_kernel(tv.fntype);
+
+	futex = SAFE_MALLOC(sizeof(uint32_t));
+	*futex = FUTEX_INITIALIZER;
+
+	waitv = tst_alloc(sizeof(struct futex_waitv));
+}
+
+static void init_timeout(struct timespec *to)
+{
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, to);
+	to->tv_sec++;
+}
+
+static void init_waitv(void)
+{
+	waitv->uaddr = (uintptr_t)&futex;
+	waitv->flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
+	waitv->val = 0;
+}
+
+static void test_invalid_flags(void)
+{
+	struct timespec to;
+	int res;
+
+	init_waitv();
+	init_timeout(&to);
+
+	/* Testing a waiter without FUTEX_32 flag */
+	waitv->flags = FUTEX_PRIVATE_FLAG;
+
+	res = futex_waitv(waitv, 1, 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 invalid flags");
+	}
+}
+
+static void test_unaligned_address(void)
+{
+	struct timespec to;
+	int res;
+
+	init_waitv();
+	init_timeout(&to);
+
+	/* Testing a waiter with an unaligned address */
+	waitv->uaddr = 1;
+
+	res = futex_waitv(waitv, 1, 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 unligned address");
+	}
+}
+
+static void test_null_address(void)
+{
+	struct timespec to;
+	int res;
+
+	init_waitv();
+	init_timeout(&to);
+
+	/* Testing a NULL address */
+	waitv->uaddr = 0x00000000;
+
+	res = futex_waitv(waitv, 1, 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 address is NULL");
+	}
+}
+
+static void test_null_waiters(void)
+{
+	struct timespec to;
+	int res;
+
+	init_timeout(&to);
+
+	/* Testing a NULL address for *waiters */
+	res = futex_waitv(NULL, 1, 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 waiters are NULL");
+	}
+}
+
+static void test_invalid_clockid(void)
+{
+	struct timespec to;
+	int res;
+
+	init_waitv();
+	init_timeout(&to);
+
+	/* Testing an invalid clockid */
+	res = futex_waitv(waitv, 1, 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 void run(void)
+{
+	test_invalid_flags();
+	test_unaligned_address();
+	test_null_address();
+	test_null_waiters();
+	test_invalid_clockid();
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.min_kver = "5.16",
+	.bufs =
+		(struct tst_buffers[]){
+			{ &waitv, .size = sizeof(*waitv) },
+			{},
+		},
+};
diff --git a/testcases/kernel/syscalls/futex/futex_waitv02.c b/testcases/kernel/syscalls/futex/futex_waitv02.c
new file mode 100644
index 000000000..d58de293f
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_waitv02.c
@@ -0,0 +1,111 @@
+// 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.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <time.h>
+#include "tst_test.h"
+#include "lapi/futex.h"
+#include "lapi/syscalls.h"
+#include "futex2test.h"
+#include "tst_safe_pthread.h"
+#include "tst_safe_clocks.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_res(TINFO, "Testing variant: %s", tv.desc);
+	futex_supported_by_kernel(tv.fntype);
+
+	tst_syscall(__NR_gettid);
+
+	if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
+		tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
+
+	futexes = tst_alloc(sizeof(uint32_t) * numfutex);
+	memset(futexes, 0, numfutex);
+
+	waitv = tst_alloc(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 *threaded(void *arg)
+{
+	struct futex_test_variants tv;
+	int ret, tid = *(int *)arg;
+
+	tv = futex_variants();
+	TST_THREAD_STATE_WAIT(tid, '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, tid;
+	pthread_t t;
+
+	tid = tst_syscall(__NR_gettid);
+
+	SAFE_PTHREAD_CREATE(&t, NULL, threaded, (void *)&tid);
+
+	/* setting absolute timeout for futex2 */
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &to);
+	to.tv_sec++;
+
+	ret = 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,
+	.min_kver = "5.16",
+	.bufs =
+		(struct tst_buffers[]){
+			{ &waitv, .size = sizeof(*waitv) },
+			{ &futexes, .size = sizeof(*futexes) },
+			{},
+		},
+	.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..4f3b83ff1
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_waitv03.c
@@ -0,0 +1,122 @@
+// 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.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <time.h>
+#include <sys/shm.h>
+#include "tst_test.h"
+#include "lapi/futex.h"
+#include "lapi/syscalls.h"
+#include "futex2test.h"
+#include "tst_safe_pthread.h"
+#include "tst_safe_clocks.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_res(TINFO, "Testing variant: %s", tv.desc);
+	futex_supported_by_kernel(tv.fntype);
+
+	tst_syscall(__NR_gettid);
+
+	if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
+		tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
+
+	waitv = tst_alloc(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);
+}
+
+static void *threaded(void *arg)
+{
+	struct futex_test_variants tv;
+	int ret, tid = *(int *)arg;
+
+	tv = futex_variants();
+	TST_THREAD_STATE_WAIT(tid, '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, tid;
+	pthread_t t;
+
+	tid = tst_syscall(__NR_gettid);
+
+	SAFE_PTHREAD_CREATE(&t, NULL, threaded, (void *)&tid);
+
+	/* setting absolute timeout for futex2 */
+	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &to);
+	to.tv_sec++;
+
+	ret = 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",
+	.bufs =
+		(struct tst_buffers[]){
+			{ &waitv, .size = sizeof(*waitv) },
+			{},
+		},
+	.options =
+		(struct tst_option[]){
+			{ "n:", &str_numfutex, "Number of futex (default 30)" },
+			{},
+		},
+};
diff --git a/testcases/kernel/syscalls/futex/futextest.h b/testcases/kernel/syscalls/futex/futextest.h
index 3f2f36fef..cd925e686 100644
--- a/testcases/kernel/syscalls/futex/futextest.h
+++ b/testcases/kernel/syscalls/futex/futextest.h
@@ -16,52 +16,11 @@
 #include <unistd.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
-#include <linux/futex.h>
 #include "lapi/futex.h"
 #include "tst_timer.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 +33,21 @@ struct futex_test_variants {
 	char *desc;
 };
 
+static inline struct futex_test_variants futex_variants(void)
+{
+	struct futex_test_variants 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
+	};
+
+	return variants[tst_variant];
+}
+
 static inline void futex_supported_by_kernel(enum futex_fn_type fntype)
 {
 	if (fntype != FUTEX_FN_FUTEX64)
@@ -318,4 +292,4 @@ futex_set(futex_t *uaddr, u_int32_t newval)
 	return newval;
 }
 
-#endif
+#endif /* _FUTEXTEST_H */
-- 
2.34.1


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

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

* Re: [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro
  2022-02-07 14:41 ` [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro Andrea Cervesato
@ 2022-02-08 11:09   ` Cyril Hrubis
  2022-02-09  8:39     ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 8+ messages in thread
From: Cyril Hrubis @ 2022-02-08 11:09 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> The TST_THREAD_STATE_WAIT macro can be used to wait and check for
> pthread state changes.
> 
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de>
> ---
>  include/tst_test.h         |  1 +
>  include/tst_thread_state.h | 33 +++++++++++++++++++++++++++++++++
>  lib/tst_thread_state.c     | 37 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 71 insertions(+)
>  create mode 100644 include/tst_thread_state.h
>  create mode 100644 lib/tst_thread_state.c
> 
> diff --git a/include/tst_test.h b/include/tst_test.h
> index 450ddf086..79067f3bf 100644
> --- a/include/tst_test.h
> +++ b/include/tst_test.h
> @@ -27,6 +27,7 @@
>  #include "tst_cmd.h"
>  #include "tst_cpu.h"
>  #include "tst_process_state.h"
> +#include "tst_thread_state.h"
>  #include "tst_atomic.h"
>  #include "tst_kvercmp.h"
>  #include "tst_kernel.h"
> diff --git a/include/tst_thread_state.h b/include/tst_thread_state.h
> new file mode 100644
> index 000000000..4d6a345b8
> --- /dev/null
> +++ b/include/tst_thread_state.h
> @@ -0,0 +1,33 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> + */
> +
> +/*
> + * These functions helps you wait till a thread with given tpid changes state.
> + */
> +
> +#ifndef TST_THREAD_STATE__
> +#define TST_THREAD_STATE__
> +
> +#include <unistd.h>
> +
> +/*
> + * Waits for thread state change.
> + *
> + * The state is one of the following:
> + *
> + * R - running
> + * S - sleeping
> + * D - disk sleep
> + * T - stopped
> + * t - tracing stopped
> + * Z - zombie
> + * X - dead
> + */
> +#define TST_THREAD_STATE_WAIT(tid, state, msec_timeout) \
> +	tst_thread_state_wait((tid), (state), (msec_timeout))
> +
> +int tst_thread_state_wait(pid_t tid, const char state, unsigned int msec_timeout);
> +
> +#endif /* TST_THREAD_STATE__ */
> diff --git a/lib/tst_thread_state.c b/lib/tst_thread_state.c
> new file mode 100644
> index 000000000..f5580c39e
> --- /dev/null
> +++ b/lib/tst_thread_state.c
> @@ -0,0 +1,37 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> + */
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <errno.h>
> +
> +#include "tst_safe_file_ops.h"
> +#include "tst_thread_state.h"
> +
> +int tst_thread_state_wait(pid_t tid, const char state, unsigned int msec_timeout)
> +{
> +	char proc_path[128], cur_state;
> +	unsigned int msecs = 0;
> +
> +	snprintf(proc_path, sizeof(proc_path), "/proc/self/task/%i/stat", tid);
> +
> +	for (;;) {
> +		SAFE_FILE_SCANF(proc_path, "%*i %*s %c", &cur_state);
> +
> +		if (state == cur_state)
> +			break;
> +
> +		usleep(1000);
> +		msecs += 1;
> +
> +		if (msec_timeout && msecs >= msec_timeout) {
> +			errno = ETIMEDOUT;
> +			return -1;
> +		}
> +	}
> +
> +	return 0;
> +}

Maybe we can just put this code into the existing tst_process_state.h
header and C source.

And we should add some documentaion about the function into the
doc/c-test-api.txt as well.

Other than that it looks good.

-- 
Cyril Hrubis
chrubis@suse.cz

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

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

* Re: [LTP] [PATCH v4 3/3] Add futex_waitv testing suite
  2022-02-07 14:41 ` [LTP] [PATCH v4 3/3] Add futex_waitv testing suite Andrea Cervesato
@ 2022-02-08 11:49   ` Cyril Hrubis
  0 siblings, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2022-02-08 11:49 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de>
> ---
> v4 introduces guarded buffers, more safe macros and TST_THREAD_STATE_WAIT usage.
> 
>  testcases/kernel/syscalls/futex/.gitignore    |   3 +
>  testcases/kernel/syscalls/futex/Makefile      |  14 +-
>  testcases/kernel/syscalls/futex/futex2test.h  |  30 ++++
>  .../kernel/syscalls/futex/futex_waitv01.c     | 162 ++++++++++++++++++
>  .../kernel/syscalls/futex/futex_waitv02.c     | 111 ++++++++++++
>  .../kernel/syscalls/futex/futex_waitv03.c     | 122 +++++++++++++
>  testcases/kernel/syscalls/futex/futextest.h   |  58 ++-----
>  7 files changed, 456 insertions(+), 44 deletions(-)
>  create mode 100644 testcases/kernel/syscalls/futex/futex2test.h
>  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/futex2test.h b/testcases/kernel/syscalls/futex/futex2test.h
> new file mode 100644
> index 000000000..ec3667376
> --- /dev/null
> +++ b/testcases/kernel/syscalls/futex/futex2test.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Futex2 library addons for futex tests
> + *
> + * Copyright 2021 Collabora Ltd.
> + * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> + */
> +
> +#ifndef _FUTEX2TEST_H
> +#define _FUTEX2TEST_H

Please do not use indentifiers starting with underscore, these are
reserved for system libraries and kernel.

> +
> +#include <stdint.h>
> +#include "lapi/syscalls.h"
> +#include "futextest.h"
> +
> +/**
> + * 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 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 /* _FUTEX2TEST_H */
> \ No newline at end of file

Please make sure that there are newlines at the end of the files.

> diff --git a/testcases/kernel/syscalls/futex/futex_waitv01.c b/testcases/kernel/syscalls/futex/futex_waitv01.c
> new file mode 100644
> index 000000000..928740c2f
> --- /dev/null
> +++ b/testcases/kernel/syscalls/futex/futex_waitv01.c
> @@ -0,0 +1,162 @@
> +// 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 <time.h>
> +#include "tst_test.h"
> +#include "lapi/futex.h"
> +#include "futex2test.h"
> +#include "tst_safe_clocks.h"
> +
> +static uint32_t *futex;
> +static struct futex_waitv *waitv;
> +
> +static void setup(void)
> +{
> +	struct futex_test_variants tv;
> +
> +	tv = futex_variants();
> +
> +	tst_res(TINFO, "Testing variant: %s", tv.desc);
> +	futex_supported_by_kernel(tv.fntype);

Unlike other tests this one does not actually use different variants of
the syscall nor it sets the .variants field in tst_test, so this part is
useless.

> +	futex = SAFE_MALLOC(sizeof(uint32_t));
> +	*futex = FUTEX_INITIALIZER;
> +
> +	waitv = tst_alloc(sizeof(struct futex_waitv));

There is no need to allocate waitv here, it has been allcated allready
since it's passed in the tst_buffers array in tst_test structure.

> +}
> +
> +static void init_timeout(struct timespec *to)
> +{
> +	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, to);
> +	to->tv_sec++;
> +}
> +
> +static void init_waitv(void)
> +{
> +	waitv->uaddr = (uintptr_t)&futex;
> +	waitv->flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
> +	waitv->val = 0;
> +}
> +
> +static void test_invalid_flags(void)
> +{
> +	struct timespec to;
> +	int res;
> +
> +	init_waitv();
> +	init_timeout(&to);
> +
> +	/* Testing a waiter without FUTEX_32 flag */
> +	waitv->flags = FUTEX_PRIVATE_FLAG;
> +
> +	res = futex_waitv(waitv, 1, 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 invalid flags");
> +	}

This does not seem to make any sense.

I think that you got confused here by the fact that futex_waitv()
behaves differently when called by the tst_syscall() wrapper. As far as
I can tell it does return -1 and sets errno in a case of a failure, so
we should be able to use TST_EXP_FAIL() here and in the rest of the
tests.

> +}
> +
> +static void test_unaligned_address(void)
> +{
> +	struct timespec to;
> +	int res;
> +
> +	init_waitv();
> +	init_timeout(&to);
> +
> +	/* Testing a waiter with an unaligned address */
> +	waitv->uaddr = 1;
> +
> +	res = futex_waitv(waitv, 1, 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 unligned address");
> +	}
> +}
> +
> +static void test_null_address(void)
> +{
> +	struct timespec to;
> +	int res;
> +
> +	init_waitv();
> +	init_timeout(&to);
> +
> +	/* Testing a NULL address */
> +	waitv->uaddr = 0x00000000;
> +
> +	res = futex_waitv(waitv, 1, 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 address is NULL");
> +	}
> +}
> +
> +static void test_null_waiters(void)
> +{
> +	struct timespec to;
> +	int res;
> +
> +	init_timeout(&to);
> +
> +	/* Testing a NULL address for *waiters */
> +	res = futex_waitv(NULL, 1, 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 waiters are NULL");
> +	}
> +}
> +
> +static void test_invalid_clockid(void)
> +{
> +	struct timespec to;
> +	int res;
> +
> +	init_waitv();
> +	init_timeout(&to);
> +
> +	/* Testing an invalid clockid */
> +	res = futex_waitv(waitv, 1, 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 void run(void)
> +{
> +	test_invalid_flags();
> +	test_unaligned_address();
> +	test_null_address();
> +	test_null_waiters();
> +	test_invalid_clockid();
> +}
> +
> +static struct tst_test test = {
> +	.test_all = run,
> +	.setup = setup,
> +	.min_kver = "5.16",
> +	.bufs =
> +		(struct tst_buffers[]){
> +			{ &waitv, .size = sizeof(*waitv) },
> +			{},
> +		},
> +};
> diff --git a/testcases/kernel/syscalls/futex/futex_waitv02.c b/testcases/kernel/syscalls/futex/futex_waitv02.c
> new file mode 100644
> index 000000000..d58de293f
> --- /dev/null
> +++ b/testcases/kernel/syscalls/futex/futex_waitv02.c
> @@ -0,0 +1,111 @@
> +// 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.
> + */
> +
> +#define _GNU_SOURCE
> +#include <unistd.h>
> +#include <time.h>
> +#include "tst_test.h"
> +#include "lapi/futex.h"
> +#include "lapi/syscalls.h"
> +#include "futex2test.h"
> +#include "tst_safe_pthread.h"
> +#include "tst_safe_clocks.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_res(TINFO, "Testing variant: %s", tv.desc);
> +	futex_supported_by_kernel(tv.fntype);

Since this test actually uses the function from variants it must set the
.variants filed in the test_test structure.

> +	tst_syscall(__NR_gettid);
> +
> +	if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
> +		tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
> +
> +	futexes = tst_alloc(sizeof(uint32_t) * numfutex);
> +	memset(futexes, 0, numfutex);
> +
> +	waitv = tst_alloc(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;
> +	}

Since these two are allocated dynamically based on a commandline
parameter we have to allocate them here and not by passing the pointers
into the tst_test structure.

> +}
> +
> +static void *threaded(void *arg)
> +{
> +	struct futex_test_variants tv;
> +	int ret, tid = *(int *)arg;
> +
> +	tv = futex_variants();
> +	TST_THREAD_STATE_WAIT(tid, '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, tid;
> +	pthread_t t;
> +
> +	tid = tst_syscall(__NR_gettid);
> +
> +	SAFE_PTHREAD_CREATE(&t, NULL, threaded, (void *)&tid);
> +
> +	/* setting absolute timeout for futex2 */
> +	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &to);
> +	to.tv_sec++;
> +
> +	ret = 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);

Here as well, the tst_sycall() wrapper should set the errno instead of
returning the -err.

> +	SAFE_PTHREAD_JOIN(t, NULL);
> +	tst_res(TPASS, "futex_waitv returned correctly");
> +}
> +
> +static struct tst_test test = {
> +	.test_all = run,
> +	.setup = setup,
> +	.min_kver = "5.16",
> +	.bufs =
> +		(struct tst_buffers[]){
> +			{ &waitv, .size = sizeof(*waitv) },
> +			{ &futexes, .size = sizeof(*futexes) },
> +			{},
> +		},
> +	.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..4f3b83ff1
> --- /dev/null
> +++ b/testcases/kernel/syscalls/futex/futex_waitv03.c
> @@ -0,0 +1,122 @@
> +// 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.
> + */
> +
> +#define _GNU_SOURCE
> +#include <unistd.h>
> +#include <time.h>
> +#include <sys/shm.h>
> +#include "tst_test.h"
> +#include "lapi/futex.h"
> +#include "lapi/syscalls.h"
> +#include "futex2test.h"
> +#include "tst_safe_pthread.h"
> +#include "tst_safe_clocks.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_res(TINFO, "Testing variant: %s", tv.desc);
> +	futex_supported_by_kernel(tv.fntype);

Here as well .variants in the tst_test structure.

> +	tst_syscall(__NR_gettid);

What is this useful for?

> +	if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX))
> +		tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex);
> +
> +	waitv = tst_alloc(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");

We do have SAFE_SHMGET()

> +		unsigned int *shared_data = shmat(shm_id, NULL, 0);

And SAFE_SHMAT()

> +		waitv[i].uaddr = (uintptr_t)shared_data;
> +		waitv[i].flags = FUTEX_32;
> +		waitv[i].val = 0;
> +	}

Here as well can't be allocated by passing pointer in tst_test
structure.

> +}
> +
> +static void cleanup(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < numfutex; i++)
> +		shmdt((void *)(uintptr_t)waitv[i].uaddr);

I guess that we should only detach what was previously attached. Maybe
just memset the waitv to 0 first then do SAFE_SHMDT() for any non-zero
uaddr.

> +}
> +
> +static void *threaded(void *arg)
> +{
> +	struct futex_test_variants tv;
> +	int ret, tid = *(int *)arg;
> +
> +	tv = futex_variants();
> +	TST_THREAD_STATE_WAIT(tid, '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, tid;
> +	pthread_t t;
> +
> +	tid = tst_syscall(__NR_gettid);
> +
> +	SAFE_PTHREAD_CREATE(&t, NULL, threaded, (void *)&tid);
> +
> +	/* setting absolute timeout for futex2 */
> +	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &to);
> +	to.tv_sec++;
> +
> +	ret = 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);

And here as well.

> +	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",
> +	.bufs =
> +		(struct tst_buffers[]){
> +			{ &waitv, .size = sizeof(*waitv) },
> +			{},
> +		},
> +	.options =
> +		(struct tst_option[]){
> +			{ "n:", &str_numfutex, "Number of futex (default 30)" },
> +			{},
> +		},
> +};
> diff --git a/testcases/kernel/syscalls/futex/futextest.h b/testcases/kernel/syscalls/futex/futextest.h
> index 3f2f36fef..cd925e686 100644
> --- a/testcases/kernel/syscalls/futex/futextest.h
> +++ b/testcases/kernel/syscalls/futex/futextest.h
> @@ -16,52 +16,11 @@
>  #include <unistd.h>
>  #include <sys/syscall.h>
>  #include <sys/types.h>
> -#include <linux/futex.h>
>  #include "lapi/futex.h"
>  #include "tst_timer.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 +33,21 @@ struct futex_test_variants {
>  	char *desc;
>  };
>  
> +static inline struct futex_test_variants futex_variants(void)
> +{
> +	struct futex_test_variants 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
> +	};
> +
> +	return variants[tst_variant];
> +}

We also need FUTEX_VARIANTS constant defined to 2 here so that we can
add it to the tst_test structure as .test_variants initialized.

Also it will be slight better it this function returned pointer to a
const data as:


static inline const struct futex_test_variants *futex_variant(void)
{
	...
}

>  static inline void futex_supported_by_kernel(enum futex_fn_type fntype)
>  {
>  	if (fntype != FUTEX_FN_FUTEX64)
> @@ -318,4 +292,4 @@ futex_set(futex_t *uaddr, u_int32_t newval)
>  	return newval;
>  }
>  
> -#endif
> +#endif /* _FUTEXTEST_H */
> -- 
> 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] 8+ messages in thread

* Re: [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro
  2022-02-08 11:09   ` Cyril Hrubis
@ 2022-02-09  8:39     ` Andrea Cervesato via ltp
  2022-02-09 10:35       ` Cyril Hrubis
  0 siblings, 1 reply; 8+ messages in thread
From: Andrea Cervesato via ltp @ 2022-02-09  8:39 UTC (permalink / raw)
  To: Cyril Hrubis, Andrea Cervesato; +Cc: ltp


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

Hi!

On 2/8/22 12:09, Cyril Hrubis wrote:
> Hi!
>> The TST_THREAD_STATE_WAIT macro can be used to wait and check for
>> pthread state changes.
>>
>> Signed-off-by: Andrea Cervesato<andrea.cervesato@suse.de>
>> ---
>>   include/tst_test.h         |  1 +
>>   include/tst_thread_state.h | 33 +++++++++++++++++++++++++++++++++
>>   lib/tst_thread_state.c     | 37 +++++++++++++++++++++++++++++++++++++
>>   3 files changed, 71 insertions(+)
>>   create mode 100644 include/tst_thread_state.h
>>   create mode 100644 lib/tst_thread_state.c
>>
>> diff --git a/include/tst_test.h b/include/tst_test.h
>> index 450ddf086..79067f3bf 100644
>> --- a/include/tst_test.h
>> +++ b/include/tst_test.h
>> @@ -27,6 +27,7 @@
>>   #include "tst_cmd.h"
>>   #include "tst_cpu.h"
>>   #include "tst_process_state.h"
>> +#include "tst_thread_state.h"
>>   #include "tst_atomic.h"
>>   #include "tst_kvercmp.h"
>>   #include "tst_kernel.h"
>> diff --git a/include/tst_thread_state.h b/include/tst_thread_state.h
>> new file mode 100644
>> index 000000000..4d6a345b8
>> --- /dev/null
>> +++ b/include/tst_thread_state.h
>> @@ -0,0 +1,33 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (C) 2022 SUSE LLC Andrea Cervesato<andrea.cervesato@suse.com>
>> + */
>> +
>> +/*
>> + * These functions helps you wait till a thread with given tpid changes state.
>> + */
>> +
>> +#ifndef TST_THREAD_STATE__
>> +#define TST_THREAD_STATE__
>> +
>> +#include <unistd.h>
>> +
>> +/*
>> + * Waits for thread state change.
>> + *
>> + * The state is one of the following:
>> + *
>> + * R - running
>> + * S - sleeping
>> + * D - disk sleep
>> + * T - stopped
>> + * t - tracing stopped
>> + * Z - zombie
>> + * X - dead
>> + */
>> +#define TST_THREAD_STATE_WAIT(tid, state, msec_timeout) \
>> +	tst_thread_state_wait((tid), (state), (msec_timeout))
>> +
>> +int tst_thread_state_wait(pid_t tid, const char state, unsigned int msec_timeout);
>> +
>> +#endif /* TST_THREAD_STATE__ */
>> diff --git a/lib/tst_thread_state.c b/lib/tst_thread_state.c
>> new file mode 100644
>> index 000000000..f5580c39e
>> --- /dev/null
>> +++ b/lib/tst_thread_state.c
>> @@ -0,0 +1,37 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (C) 2022 SUSE LLC Andrea Cervesato<andrea.cervesato@suse.com>
>> + */
>> +
>> +#include <stdio.h>
>> +#include <unistd.h>
>> +#include <string.h>
>> +#include <errno.h>
>> +
>> +#include "tst_safe_file_ops.h"
>> +#include "tst_thread_state.h"
>> +
>> +int tst_thread_state_wait(pid_t tid, const char state, unsigned int msec_timeout)
>> +{
>> +	char proc_path[128], cur_state;
>> +	unsigned int msecs = 0;
>> +
>> +	snprintf(proc_path, sizeof(proc_path), "/proc/self/task/%i/stat", tid);
>> +
>> +	for (;;) {
>> +		SAFE_FILE_SCANF(proc_path, "%*i %*s %c", &cur_state);
>> +
>> +		if (state == cur_state)
>> +			break;
>> +
>> +		usleep(1000);
>> +		msecs += 1;
>> +
>> +		if (msec_timeout && msecs >= msec_timeout) {
>> +			errno = ETIMEDOUT;
>> +			return -1;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
> Maybe we can just put this code into the existing tst_process_state.h
> header and C source.
The tst_safe_process_state.c implementation is currently using old API 
and it's importing "test.h" . If we want to add TST_THREAD_STATE_WAIT 
into tst_process_state.h then we also need to rewrite process state 
headers/implementation files in order to support both old and new API.
>
> And we should add some documentaion about the function into the
> doc/c-test-api.txt as well.
>
> Other than that it looks good.

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

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


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

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

* Re: [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro
  2022-02-09  8:39     ` Andrea Cervesato via ltp
@ 2022-02-09 10:35       ` Cyril Hrubis
  0 siblings, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2022-02-09 10:35 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi!
> > Maybe we can just put this code into the existing tst_process_state.h
> > header and C source.
> The tst_safe_process_state.c implementation is currently using old API 
> and it's importing "test.h" . If we want to add TST_THREAD_STATE_WAIT 
> into tst_process_state.h then we also need to rewrite process state 
> headers/implementation files in order to support both old and new API.

Good point, I wouldn't bother. Maybe just use single header then and
keep the implementation split?

-- 
Cyril Hrubis
chrubis@suse.cz

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

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

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

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-07 14:41 [LTP] [PATCH v4 0/3] Add futex_wait testing suite Andrea Cervesato
2022-02-07 14:41 ` [LTP] [PATCH v4 1/3] Add TST_THREAD_STATE_WAIT macro Andrea Cervesato
2022-02-08 11:09   ` Cyril Hrubis
2022-02-09  8:39     ` Andrea Cervesato via ltp
2022-02-09 10:35       ` Cyril Hrubis
2022-02-07 14:41 ` [LTP] [PATCH v4 2/3] Update lapi/futex.h fallback Andrea Cervesato
2022-02-07 14:41 ` [LTP] [PATCH v4 3/3] Add futex_waitv testing suite Andrea Cervesato
2022-02-08 11:49   ` 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.