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