[PATCH v2 2/2] selftests: futex: Use a 64-bit time_t
From: Alistair Francis <hidden>
Date: 2021-10-15 00:57:14
Also in:
linux-riscv, lkml
Subsystem:
futex subsystem, kernel selftest framework, the rest · Maintainers:
Thomas Gleixner, Ingo Molnar, Shuah Khan, Linus Torvalds
From: Alistair Francis <redacted> Convert the futex selftests to only use a 64-bit time_t. On 64-bit architectures this isn't a functional change. On 32-bit architectures we now only perform 64-bit time_t syscalls (__NR_futex_time64) and use a struct timespec64. This won't work on kernels before 5.1, but as perf is tied to the kernel that's ok. This allows the tests to run and pass on RISC-V 32-bit. Signed-off-by: Alistair Francis <redacted> --- .../futex/functional/futex_requeue.c | 2 +- .../futex/functional/futex_requeue_pi.c | 10 ++--- .../selftests/futex/functional/futex_wait.c | 2 +- .../futex_wait_private_mapped_file.c | 2 +- .../futex/functional/futex_wait_timeout.c | 8 ++-- .../futex/functional/futex_wait_wouldblock.c | 2 +- .../selftests/futex/include/futextest.h | 37 +++++++++++++++---- 7 files changed, 43 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_requeue.c b/tools/testing/selftests/futex/functional/futex_requeue.c
index 51485be6eb2f1..f51aedffcd161 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue.c@@ -27,7 +27,7 @@ void usage(char *prog) void *waiterfn(void *arg) { - struct timespec to; + struct timespec64 to; to.tv_sec = 0; to.tv_nsec = timeout_ns;
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi.c b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
index 1ee5518ee6b7f..32d6ee554ec2e 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi.c@@ -48,7 +48,7 @@ static int locked; struct thread_arg { long id; - struct timespec *timeout; + struct timespec64 *timeout; int lock; int ret; };
@@ -281,7 +281,7 @@ int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns) struct thread_arg blocker_arg = THREAD_ARG_INITIALIZER; struct thread_arg waker_arg = THREAD_ARG_INITIALIZER; pthread_t waiter[THREAD_MAX], waker, blocker; - struct timespec ts, *tsp = NULL; + struct timespec64 ts, *tsp = NULL; struct thread_arg args[THREAD_MAX]; int *waiter_ret; int i, ret = RET_PASS;
@@ -290,12 +290,12 @@ int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns) time_t secs; info("timeout_ns = %ld\n", timeout_ns); - ret = clock_gettime(CLOCK_MONOTONIC, &ts); + ret = gettime64(CLOCK_MONOTONIC, &ts); secs = (ts.tv_nsec + timeout_ns) / 1000000000; ts.tv_nsec = ((int64_t)ts.tv_nsec + timeout_ns) % 1000000000; ts.tv_sec += secs; - info("ts.tv_sec = %ld\n", ts.tv_sec); - info("ts.tv_nsec = %ld\n", ts.tv_nsec); + info("ts.tv_sec = %lld\n", ts.tv_sec); + info("ts.tv_nsec = %lld\n", ts.tv_nsec); tsp = &ts; }
diff --git a/tools/testing/selftests/futex/functional/futex_wait.c b/tools/testing/selftests/futex/functional/futex_wait.c
index 685140d9b93d2..d1c8a4212c74c 100644
--- a/tools/testing/selftests/futex/functional/futex_wait.c
+++ b/tools/testing/selftests/futex/functional/futex_wait.c@@ -30,7 +30,7 @@ void usage(char *prog) static void *waiterfn(void *arg) { - struct timespec to; + struct timespec64 to; unsigned int flags = 0; if (arg)
diff --git a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
index fb4148f23fa37..5e84e136ad99e 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c@@ -38,7 +38,7 @@ futex_t val = 1; char pad2[PAGE_SZ] = {1}; #define WAKE_WAIT_US 3000000 -struct timespec wait_timeout = { .tv_sec = 5, .tv_nsec = 0}; +struct timespec64 wait_timeout = { .tv_sec = 5, .tv_nsec = 0}; void usage(char *prog) {
diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
index 1f8f6daaf1e70..86b1e847a0246 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c@@ -71,11 +71,11 @@ static void test_timeout(int res, int *ret, char *test_name, int err) /* * Calculate absolute timeout and correct overflow */ -static int futex_get_abs_timeout(clockid_t clockid, struct timespec *to, +static int futex_get_abs_timeout(clockid_t clockid, struct timespec64 *to, long timeout_ns) { - if (clock_gettime(clockid, to)) { - error("clock_gettime failed\n", errno); + if (gettime64(clockid, to)) { + error("gettime64 failed\n", errno); return errno; }
@@ -93,7 +93,7 @@ int main(int argc, char *argv[]) { futex_t f1 = FUTEX_INITIALIZER; int res, ret = RET_PASS; - struct timespec to; + struct timespec64 to; pthread_t thread; int c;
diff --git a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
index 0ae390ff81644..76faa664544d6 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c@@ -38,7 +38,7 @@ void usage(char *prog) int main(int argc, char *argv[]) { - struct timespec to = {.tv_sec = 0, .tv_nsec = timeout_ns}; + struct timespec64 to = {.tv_sec = 0, .tv_nsec = timeout_ns}; futex_t f1 = FUTEX_INITIALIZER; int res, ret = RET_PASS; int c;
diff --git a/tools/testing/selftests/futex/include/futextest.h b/tools/testing/selftests/futex/include/futextest.h
index ddbcfc9b7bac4..67ed97a455274 100644
--- a/tools/testing/selftests/futex/include/futextest.h
+++ b/tools/testing/selftests/futex/include/futextest.h@@ -21,6 +21,7 @@ #include <sys/syscall.h> #include <sys/types.h> #include <linux/futex.h> +#include <linux/time_types.h> typedef volatile u_int32_t futex_t; #define FUTEX_INITIALIZER 0
@@ -47,12 +48,14 @@ typedef volatile u_int32_t futex_t; FUTEX_PRIVATE_FLAG) #endif +#define timespec64 __kernel_timespec + /** * futex() - SYS_futex syscall wrapper * @uaddr: address of first futex * @op: futex op code * @val: typically expected value of uaddr, but varies by op - * @timeout: typically an absolute struct timespec (except where noted + * @timeout: typically an absolute struct timespec64 (except where noted * otherwise). Overloaded by some ops * @uaddr2: address of second futex for some ops\ * @val3: varies by op
@@ -67,15 +70,35 @@ typedef volatile u_int32_t futex_t; * These argument descriptions are the defaults for all * like-named arguments in the following wrappers except where noted below. */ -#define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \ - syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3) +/** + * We only support 64-bit time_t for the timeout. + * On 64-bit architectures we can use __NR_futex + * On 32-bit architectures we use __NR_futex_time64. This only works on kernel + * versions 5.1+. + */ +#if __BITS_PER_LONG == 64 +# define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \ + syscall(__NR_futex, uaddr, op | opflags, val, timeout, uaddr2, val3) +#else +# define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \ + syscall(__NR_futex_time64, uaddr, op | opflags, val, timeout, uaddr2, val3) +#endif + +static inline int gettime64(clock_t clockid, struct timespec64 *tv) +{ +#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) + return syscall(__NR_clock_gettime, clockid, tv); +#else + return syscall(__NR_clock_gettime64, clockid, tv); +#endif +} /** * futex_wait() - block on uaddr with optional timeout * @timeout: relative timeout */ static inline int -futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags) +futex_wait(futex_t *uaddr, futex_t val, struct timespec64 *timeout, int opflags) { return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags); }
@@ -95,7 +118,7 @@ futex_wake(futex_t *uaddr, int nr_wake, int opflags) * @bitset: bitset to be used with futex_wake_bitset */ static inline int -futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout, +futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec64 *timeout, u_int32_t bitset, int opflags) { return futex(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
@@ -118,7 +141,7 @@ futex_wake_bitset(futex_t *uaddr, int nr_wake, u_int32_t bitset, int opflags) * @detect: whether (1) or not (0) to perform deadlock detection */ static inline int -futex_lock_pi(futex_t *uaddr, struct timespec *timeout, int detect, +futex_lock_pi(futex_t *uaddr, struct timespec64 *timeout, int detect, int opflags) { return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
@@ -183,7 +206,7 @@ futex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake, */ static inline int futex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2, - struct timespec *timeout, int opflags) + struct timespec64 *timeout, int opflags) { return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0, opflags);
--
2.31.1