From: Alistair Francis <[email protected]>
Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
time_t and as such don't have the SYS_futex syscall. This patch will
allow us to use the SYS_futex_time64 syscall on those platforms.
This also converts the futex calls to be y2038 safe (when built for a
5.1+ kernel).
This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
"Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
The original commit was reverted as including linux/time_types.h would
fail to compile on older kernels. This commit doesn't include
linux/time_types.h to avoid this issue.
Signed-off-by: Alistair Francis <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alistair Francis <[email protected]>
Cc: Atish Patra <[email protected]>
Cc: Darren Hart <[email protected]>
Cc: Davidlohr Bueso <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: [email protected]
Cc: Arnaldo Carvalho de Melo <[email protected]>
Reviewed-by: Arnd Bergmann <[email protected]>
---
tools/perf/bench/futex.h | 52 +++++++++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index ebdc2b032afc..385d2bdfaa9f 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -8,6 +8,7 @@
#ifndef _FUTEX_H
#define _FUTEX_H
+#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
@@ -28,7 +29,17 @@ struct bench_futex_parameters {
};
/**
- * futex_syscall() - SYS_futex syscall wrapper
+ * This is copied from linux/time_types.h.
+ * We copy this here to avoid compilation failures when running
+ * on systems that don't ship with linux/time_types.h.
+ */
+struct __kernel_old_timespec {
+ __kernel_old_time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+
+/**
+ * futex_syscall() - __NR_futex syscall wrapper
* @uaddr: address of first futex
* @op: futex op code
* @val: typically expected value of uaddr, but varies by op
@@ -49,14 +60,49 @@ static inline int
futex_syscall(volatile u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout,
volatile u_int32_t *uaddr2, int val3, int opflags)
{
- return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
+#if defined(__NR_futex_time64)
+ if (sizeof(*timeout) != sizeof(struct __kernel_old_timespec)) {
+ int ret = syscall(__NR_futex_time64, uaddr, op | opflags, val, timeout,
+ uaddr2, val3);
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+ }
+#endif
+
+#if defined(__NR_futex)
+ if (sizeof(*timeout) == sizeof(struct __kernel_old_timespec))
+ return syscall(__NR_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
+
+ if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
+ struct __kernel_old_timespec ts32;
+
+ ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
+ ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
+
+ return syscall(__NR_futex, uaddr, op | opflags, val, ts32, uaddr2, val3);
+ } else if (!timeout) {
+ return syscall(__NR_futex, uaddr, op | opflags, val, NULL, uaddr2, val3);
+ }
+#endif
+
+ errno = ENOSYS;
+ return -1;
}
static inline int
futex_syscall_nr_requeue(volatile u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue,
volatile u_int32_t *uaddr2, int val3, int opflags)
{
- return syscall(SYS_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
+#if defined(__NR_futex_time64)
+ int ret = syscall(__NR_futex_time64, uaddr, op | opflags, val, nr_requeue,
+ uaddr2, val3);
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+#endif
+
+#if defined(__NR_futex)
+ return syscall(__NR_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
+#endif
}
/**
--
2.31.1
From: Alistair Francis <[email protected]>
Call the futex syscall from a function
In preparation for a more complex futex() function let's convert the
current macro into two functions. We need two functions to avoid
compiler failures as the macro is overloaded.
This will allow us to include pre-processor conditionals in the futex
syscall functions.
Signed-off-by: Alistair Francis <[email protected]>
---
.../selftests/futex/include/futextest.h | 59 +++++++++++--------
1 file changed, 34 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/futex/include/futextest.h b/tools/testing/selftests/futex/include/futextest.h
index ddbcfc9b7bac..c786fffecb8a 100644
--- a/tools/testing/selftests/futex/include/futextest.h
+++ b/tools/testing/selftests/futex/include/futextest.h
@@ -48,7 +48,7 @@ typedef volatile u_int32_t futex_t;
#endif
/**
- * futex() - SYS_futex syscall wrapper
+ * futex_syscall() - SYS_futex syscall wrapper
* @uaddr: address of first futex
* @op: futex op code
* @val: typically expected value of uaddr, but varies by op
@@ -58,17 +58,26 @@ typedef volatile u_int32_t futex_t;
* @val3: varies by op
* @opflags: flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
*
- * futex() is used by all the following futex op wrappers. It can also be
+ * futex_syscall() is used by all the following futex op wrappers. It can also be
* used for misuse and abuse testing. Generally, the specific op wrappers
- * should be used instead. It is a macro instead of an static inline function as
- * some of the types over overloaded (timeout is used for nr_requeue for
- * example).
+ * should be used instead.
*
* 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)
+static inline int
+futex_syscall(volatile u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout,
+ volatile u_int32_t *uaddr2, int val3, int opflags)
+{
+ return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
+}
+
+static inline int
+futex_syscall_nr_requeue(volatile u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue,
+ volatile u_int32_t *uaddr2, int val3, int opflags)
+{
+ return syscall(SYS_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
+}
/**
* futex_wait() - block on uaddr with optional timeout
@@ -77,7 +86,7 @@ typedef volatile u_int32_t futex_t;
static inline int
futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
{
- return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
+ return futex_syscall(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
}
/**
@@ -87,7 +96,7 @@ futex_wait(futex_t *uaddr, futex_t val, struct timespec *timeout, int opflags)
static inline int
futex_wake(futex_t *uaddr, int nr_wake, int opflags)
{
- return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
+ return futex_syscall(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
}
/**
@@ -98,8 +107,8 @@ static inline int
futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout,
u_int32_t bitset, int opflags)
{
- return futex(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
- opflags);
+ return futex_syscall(uaddr, FUTEX_WAIT_BITSET, val, timeout, NULL, bitset,
+ opflags);
}
/**
@@ -109,8 +118,8 @@ futex_wait_bitset(futex_t *uaddr, futex_t val, struct timespec *timeout,
static inline int
futex_wake_bitset(futex_t *uaddr, int nr_wake, u_int32_t bitset, int opflags)
{
- return futex(uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL, NULL, bitset,
- opflags);
+ return futex_syscall(uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL, NULL, bitset,
+ opflags);
}
/**
@@ -121,7 +130,7 @@ static inline int
futex_lock_pi(futex_t *uaddr, struct timespec *timeout, int detect,
int opflags)
{
- return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
+ return futex_syscall(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);
}
/**
@@ -130,7 +139,7 @@ futex_lock_pi(futex_t *uaddr, struct timespec *timeout, int detect,
static inline int
futex_unlock_pi(futex_t *uaddr, int opflags)
{
- return futex(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags);
+ return futex_syscall(uaddr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0, opflags);
}
/**
@@ -140,8 +149,8 @@ static inline int
futex_wake_op(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_wake2,
int wake_op, int opflags)
{
- return futex(uaddr, FUTEX_WAKE_OP, nr_wake, nr_wake2, uaddr2, wake_op,
- opflags);
+ return futex_syscall_nr_requeue(uaddr, FUTEX_WAKE_OP, nr_wake, nr_wake2, uaddr2, wake_op,
+ opflags);
}
/**
@@ -156,8 +165,8 @@ static inline int
futex_requeue(futex_t *uaddr, futex_t *uaddr2, int nr_wake, int nr_requeue,
int opflags)
{
- return futex(uaddr, FUTEX_REQUEUE, nr_wake, nr_requeue, uaddr2, 0,
- opflags);
+ return futex_syscall_nr_requeue(uaddr, FUTEX_REQUEUE, nr_wake, nr_requeue, uaddr2, 0,
+ opflags);
}
/**
@@ -169,8 +178,8 @@ static inline int
futex_cmp_requeue(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
int nr_requeue, int opflags)
{
- return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
- val, opflags);
+ return futex_syscall_nr_requeue(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
+ val, opflags);
}
/**
@@ -185,8 +194,8 @@ static inline int
futex_wait_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2,
struct timespec *timeout, int opflags)
{
- return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
- opflags);
+ return futex_syscall(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
+ opflags);
}
/**
@@ -200,8 +209,8 @@ static inline int
futex_cmp_requeue_pi(futex_t *uaddr, futex_t val, futex_t *uaddr2, int nr_wake,
int nr_requeue, int opflags)
{
- return futex(uaddr, FUTEX_CMP_REQUEUE_PI, nr_wake, nr_requeue, uaddr2,
- val, opflags);
+ return futex_syscall_nr_requeue(uaddr, FUTEX_CMP_REQUEUE_PI, nr_wake, nr_requeue, uaddr2,
+ val, opflags);
}
/**
--
2.31.1
From: Alistair Francis <[email protected]>
This commit adds two futex syscall wrappers that are exposed to
userspace.
Neither the kernel or glibc currently expose a futex wrapper, so
userspace is left performing raw syscalls. This has mostly been because
the overloading of one of the arguments makes it impossible to provide a
single type safe function.
Until recently the single syscall has worked fine. With the introduction
of a 64-bit time_t futex call on 32-bit architectures, this has become
more complex. The logic of handling the two possible futex syscalls is
complex and often implemented incorrectly.
This patch adds two futex syscall functions that correctly handle the
time_t complexity for userspace.
This idea is based on previous discussions:
https://lore.kernel.org/lkml/CAK8P3a3x_EyCiPDpMK54y=Rtm-Wb08ym2TNiuAZgXhYrThcWTw@mail.gmail.com/
Signed-off-by: Alistair Francis <[email protected]>
---
include/uapi/linux/futex_syscall.h | 92 ++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 include/uapi/linux/futex_syscall.h
diff --git a/include/uapi/linux/futex_syscall.h b/include/uapi/linux/futex_syscall.h
new file mode 100644
index 000000000000..bac621eb319c
--- /dev/null
+++ b/include/uapi/linux/futex_syscall.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Futex syscall helper functions
+ *
+ * Copyright (C) 2021 Western Digital. All Rights Reserved.
+ *
+ * Author: Alistair Francis <[email protected]>
+ */
+#ifndef _UAPI_LINUX_FUTEX_SYSCALL_H
+#define _UAPI_LINUX_FUTEX_SYSCALL_H
+
+#include <unistd.h>
+#include <errno.h>
+#include <linux/futex.h>
+#include <linux/types.h>
+#include <linux/time_types.h>
+#include <stdint.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <time.h>
+
+/**
+ * __kernel_futex_syscall_timeout() - __NR_futex/__NR_futex_time64 syscall wrapper
+ * @uaddr: address of first futex
+ * @op: futex op code
+ * @val: typically expected value of uaddr, but varies by op
+ * @timeout: an absolute struct timespec
+ * @uaddr2: address of second futex for some ops
+ * @val3: varies by op
+ */
+static inline int
+__kernel_futex_syscall_timeout(volatile uint32_t *uaddr, int op, uint32_t val,
+ struct timespec *timeout, volatile uint32_t *uaddr2, int val3)
+{
+#if defined(__NR_futex_time64)
+ if (sizeof(*timeout) != sizeof(struct __kernel_old_timespec)) {
+ int ret = syscall(__NR_futex_time64, uaddr, op, val, timeout, uaddr2, val3);
+
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+ }
+#endif
+
+#if defined(__NR_futex)
+ if (sizeof(*timeout) == sizeof(struct __kernel_old_timespec))
+ return syscall(__NR_futex, uaddr, op, val, timeout, uaddr2, val3);
+
+ if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
+ struct __kernel_old_timespec ts_old;
+
+ ts_old.tv_sec = (__kernel_long_t) timeout->tv_sec;
+ ts_old.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
+
+ return syscall(__NR_futex, uaddr, op, val, &ts_old, uaddr2, val3);
+ } else if (!timeout) {
+ return syscall(__NR_futex, uaddr, op, val, NULL, uaddr2, val3);
+ }
+#endif
+
+ errno = ENOSYS;
+ return -1;
+}
+
+/**
+ * __kernel_futex_syscall_nr_requeue() - __NR_futex/__NR_futex_time64 syscall wrapper
+ * @uaddr: address of first futex
+ * @op: futex op code
+ * @val: typically expected value of uaddr, but varies by op
+ * @nr_requeue: an op specific meaning
+ * @uaddr2: address of second futex for some ops
+ * @val3: varies by op
+ */
+static inline int
+__kernel_futex_syscall_nr_requeue(volatile uint32_t *uaddr, int op, uint32_t val,
+ uint32_t nr_requeue, volatile uint32_t *uaddr2, int val3)
+{
+#if defined(__NR_futex_time64)
+ int ret = syscall(__NR_futex_time64, uaddr, op, val, nr_requeue, uaddr2, val3);
+
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+#endif
+
+#if defined(__NR_futex)
+ return syscall(__NR_futex, uaddr, op, val, nr_requeue, uaddr2, val3);
+#endif
+
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif /* _UAPI_LINUX_FUTEX_SYSCALL_H */
--
2.31.1
From: Alistair Francis <[email protected]>
Using the new __kernel_futex_syscall*() functions let's add support for
32-bit systems with a 64-bit time_t. We can just direclty call the
publically exposed __kernel_futex_syscall_timeout() and
__kernel_futex_syscall_nr_requeue() functions to do this.
Signed-off-by: Alistair Francis <[email protected]>
---
tools/testing/selftests/futex/functional/futex_requeue_pi.c | 2 +-
tools/testing/selftests/futex/include/futextest.h | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi.c b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
index 1ee5518ee6b7..556bf3e74755 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
@@ -294,7 +294,7 @@ int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns)
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_sec = %lld\n", (long long) ts.tv_sec);
info("ts.tv_nsec = %ld\n", ts.tv_nsec);
tsp = &ts;
}
diff --git a/tools/testing/selftests/futex/include/futextest.h b/tools/testing/selftests/futex/include/futextest.h
index c786fffecb8a..1686f94667b1 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/futex_syscall.h>
typedef volatile u_int32_t futex_t;
#define FUTEX_INITIALIZER 0
@@ -69,14 +70,14 @@ static inline int
futex_syscall(volatile u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout,
volatile u_int32_t *uaddr2, int val3, int opflags)
{
- return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
+ return __kernel_futex_syscall_timeout(uaddr, op | opflags, val, timeout, uaddr2, val3);
}
static inline int
futex_syscall_nr_requeue(volatile u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue,
volatile u_int32_t *uaddr2, int val3, int opflags)
{
- return syscall(SYS_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
+ return __kernel_futex_syscall_nr_requeue(uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
}
/**
--
2.31.1
From: Alistair Francis <[email protected]>
This commit adds a futex waitv syscall wrapper that is exposed to
userspace.
Neither the kernel or glibc currently expose a futex wrapper, so
userspace is left performing raw syscalls. As the futex_waitv syscall
always expects a 64-bit time_t this can be tricky for 32-bit systems to
get correct.
In order to avoid userspace incorrectly passing the wrong timeouts let's
expose a public helper function that ensures the kernel is passed the
correct timeout struct.
Signed-off-by: Alistair Francis <[email protected]>
Reviewed-by: Arnd Bergmann <[email protected]>
---
include/uapi/linux/futex_syscall.h | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/include/uapi/linux/futex_syscall.h b/include/uapi/linux/futex_syscall.h
index bac621eb319c..f637f05a3be0 100644
--- a/include/uapi/linux/futex_syscall.h
+++ b/include/uapi/linux/futex_syscall.h
@@ -89,4 +89,31 @@ __kernel_futex_syscall_nr_requeue(volatile uint32_t *uaddr, int op, uint32_t val
return -1;
}
+/**
+ * __kernel_futex_syscall_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
+__kernel_futex_syscall_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters,
+ unsigned long flags, struct timespec *timo, clockid_t clockid)
+{
+ /* futex_waitv expects a 64-bit time_t */
+ if (sizeof(*timo) == sizeof(struct __kernel_timespec))
+ return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, timo, clockid);
+
+ /* If the caller supplied a 32-bit time_t, convert it to 64-bit */
+ if (timo) {
+ struct __kernel_timespec ts_new;
+
+ ts_new.tv_sec = timo->tv_sec;
+ ts_new.tv_nsec = timo->tv_nsec;
+
+ return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, &ts_new, clockid);
+ } else
+ return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, NULL, clockid);
+}
+
#endif /* _UAPI_LINUX_FUTEX_SYSCALL_H */
--
2.31.1
From: Alistair Francis <[email protected]>
Use the publically exposed __kernel_futex_syscall_waitv() helper
function for the futex_waitv tests.
Signed-off-by: Alistair Francis <[email protected]>
---
tools/testing/selftests/futex/include/futex2test.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/futex/include/futex2test.h b/tools/testing/selftests/futex/include/futex2test.h
index 9d305520e849..fdc0a0a270cd 100644
--- a/tools/testing/selftests/futex/include/futex2test.h
+++ b/tools/testing/selftests/futex/include/futex2test.h
@@ -5,6 +5,7 @@
* Copyright 2021 Collabora Ltd.
*/
#include <stdint.h>
+#include <linux/futex_syscall.h>
#define u64_to_ptr(x) ((void *)(uintptr_t)(x))
@@ -18,5 +19,5 @@
static inline int futex_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters,
unsigned long flags, struct timespec *timo, clockid_t clockid)
{
- return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, timo, clockid);
+ return __kernel_futex_syscall_waitv(waiters, nr_waiters, flags, timo, clockid);
}
--
2.31.1
Em Fri, Dec 10, 2021 at 09:58:52AM +1000, Alistair Francis escreveu:
> From: Alistair Francis <[email protected]>
>
> Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
> time_t and as such don't have the SYS_futex syscall. This patch will
> allow us to use the SYS_futex_time64 syscall on those platforms.
>
> This also converts the futex calls to be y2038 safe (when built for a
> 5.1+ kernel).
>
> This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
> "Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
>
> The original commit was reverted as including linux/time_types.h would
> fail to compile on older kernels. This commit doesn't include
> linux/time_types.h to avoid this issue.
The reverted commit had:
Reviewed-by: Arnd Bergmann <[email protected]>
Acked-by: Davidlohr Bueso <[email protected]>
Does that stands for this new patch?
Thanks,
- Arnaldo
> Signed-off-by: Alistair Francis <[email protected]>
> Cc: Alexander Shishkin <[email protected]>
> Cc: Alistair Francis <[email protected]>
> Cc: Atish Patra <[email protected]>
> Cc: Darren Hart <[email protected]>
> Cc: Davidlohr Bueso <[email protected]>
> Cc: Jiri Olsa <[email protected]>
> Cc: Mark Rutland <[email protected]>
> Cc: Namhyung Kim <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Thomas Gleixner <[email protected]>
> Cc: [email protected]
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Reviewed-by: Arnd Bergmann <[email protected]>
> ---
> tools/perf/bench/futex.h | 52 +++++++++++++++++++++++++++++++++++++---
> 1 file changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
> index ebdc2b032afc..385d2bdfaa9f 100644
> --- a/tools/perf/bench/futex.h
> +++ b/tools/perf/bench/futex.h
> @@ -8,6 +8,7 @@
> #ifndef _FUTEX_H
> #define _FUTEX_H
>
> +#include <errno.h>
> #include <unistd.h>
> #include <sys/syscall.h>
> #include <sys/types.h>
> @@ -28,7 +29,17 @@ struct bench_futex_parameters {
> };
>
> /**
> - * futex_syscall() - SYS_futex syscall wrapper
> + * This is copied from linux/time_types.h.
> + * We copy this here to avoid compilation failures when running
> + * on systems that don't ship with linux/time_types.h.
> + */
> +struct __kernel_old_timespec {
> + __kernel_old_time_t tv_sec; /* seconds */
> + long tv_nsec; /* nanoseconds */
> +};
> +
> +/**
> + * futex_syscall() - __NR_futex syscall wrapper
> * @uaddr: address of first futex
> * @op: futex op code
> * @val: typically expected value of uaddr, but varies by op
> @@ -49,14 +60,49 @@ static inline int
> futex_syscall(volatile u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout,
> volatile u_int32_t *uaddr2, int val3, int opflags)
> {
> - return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
> +#if defined(__NR_futex_time64)
> + if (sizeof(*timeout) != sizeof(struct __kernel_old_timespec)) {
> + int ret = syscall(__NR_futex_time64, uaddr, op | opflags, val, timeout,
> + uaddr2, val3);
> + if (ret == 0 || errno != ENOSYS)
> + return ret;
> + }
> +#endif
> +
> +#if defined(__NR_futex)
> + if (sizeof(*timeout) == sizeof(struct __kernel_old_timespec))
> + return syscall(__NR_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
> +
> + if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
> + struct __kernel_old_timespec ts32;
> +
> + ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
> + ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
> +
> + return syscall(__NR_futex, uaddr, op | opflags, val, ts32, uaddr2, val3);
> + } else if (!timeout) {
> + return syscall(__NR_futex, uaddr, op | opflags, val, NULL, uaddr2, val3);
> + }
> +#endif
> +
> + errno = ENOSYS;
> + return -1;
> }
>
> static inline int
> futex_syscall_nr_requeue(volatile u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue,
> volatile u_int32_t *uaddr2, int val3, int opflags)
> {
> - return syscall(SYS_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
> +#if defined(__NR_futex_time64)
> + int ret = syscall(__NR_futex_time64, uaddr, op | opflags, val, nr_requeue,
> + uaddr2, val3);
> + if (ret == 0 || errno != ENOSYS)
> + return ret;
> +#endif
> +
> +#if defined(__NR_futex)
> + return syscall(__NR_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
> +#endif
> }
>
> /**
> --
> 2.31.1
--
- Arnaldo
Em Fri, Dec 10, 2021 at 09:58:52AM +1000, Alistair Francis escreveu:
> From: Alistair Francis <[email protected]>
>
> Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
> time_t and as such don't have the SYS_futex syscall. This patch will
> allow us to use the SYS_futex_time64 syscall on those platforms.
>
> This also converts the futex calls to be y2038 safe (when built for a
> 5.1+ kernel).
>
> This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
> "Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
>
> The original commit was reverted as including linux/time_types.h would
> fail to compile on older kernels. This commit doesn't include
> linux/time_types.h to avoid this issue.
10 9.99 alpine:3.12 : FAIL gcc version 9.3.0 (Alpine 9.3.0)
In file included from bench/futex-hash.c:29:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
37 | __kernel_old_time_t tv_sec; /* seconds */
| ^~~~~~~~~~~~~~~~~~~
In file included from bench/futex-wake.c:25:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
37 | __kernel_old_time_t tv_sec; /* seconds */
| ^~~~~~~~~~~~~~~~~~~
make[3]: *** [/git/perf-5.16.0-rc4/tools/build/Makefile.build:139: bench] Error 2
11 114.27 alpine:3.13 : Ok gcc (Alpine 10.2.1_pre1) 10.2.1 20201203 , Alpine clang version 10.0.1
12 100.12 alpine:3.14 : Ok gcc (Alpine 10.3.1_git20210424) 10.3.1 20210424 , Alpine clang version 11.1.0
13 101.06 alpine:3.15 : Ok gcc (Alpine 10.3.1_git20211027) 10.3.1 20211027 , Alpine clang version 12.0.1
14 101.96 alpine:edge : Ok gcc (Alpine 11.2.1_git20211128) 11.2.1 20211128 , Alpine clang version 12.0.1
15 6.98 alt:p8 : FAIL gcc version 5.3.1 20151207 (ALT p8 5.3.1-alt3.M80P.1) (GCC)
In file included from bench/futex-hash.c:29:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^
In file included from bench/futex-wake.c:25:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^
In file included from bench/futex-wake-parallel.c:31:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^
make[3]: *** [bench] Error 2
16 73.65 alt:p9 : Ok x86_64-alt-linux-gcc (GCC) 8.4.1 20200305 (ALT p9 8.4.1-alt0.p9.1) , clang version 10.0.0
17 72.34 alt:sisyphus : Ok x86_64-alt-linux-gcc (GCC) 11.2.1 20210911 (ALT Sisyphus 11.2.1-alt1) , ALT Linux Team clang version 12.0.1
18 7.58 amazonlinux:1 : FAIL gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)
In file included from bench/futex-hash.c:29:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
In file included from bench/futex-wake.c:25:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
make[3]: *** [bench] Error 2
19 8.28 amazonlinux:2 : FAIL gcc version 7.3.1 20180712 (Red Hat 7.3.1-13) (GCC)
In file included from bench/futex-hash.c:29:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
make[3]: *** [bench] Error 2
20 79.16 centos:8 : Ok gcc (GCC) 8.4.1 20200928 (Red Hat 8.4.1-1) , clang version 11.0.1 (Red Hat 11.0.1-1.module_el8.4.0+966+2995ef20)
Still building on the other containers.
- Arnaldo
Em Fri, Dec 10, 2021 at 10:36:30AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Fri, Dec 10, 2021 at 09:58:52AM +1000, Alistair Francis escreveu:
> > From: Alistair Francis <[email protected]>
> >
> > Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
> > time_t and as such don't have the SYS_futex syscall. This patch will
> > allow us to use the SYS_futex_time64 syscall on those platforms.
> >
> > This also converts the futex calls to be y2038 safe (when built for a
> > 5.1+ kernel).
> >
> > This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
> > "Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
> >
> > The original commit was reverted as including linux/time_types.h would
> > fail to compile on older kernels. This commit doesn't include
> > linux/time_types.h to avoid this issue.
>
> 10 9.99 alpine:3.12 : FAIL gcc version 9.3.0 (Alpine 9.3.0)
> In file included from bench/futex-hash.c:29:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> 37 | __kernel_old_time_t tv_sec; /* seconds */
> | ^~~~~~~~~~~~~~~~~~~
> In file included from bench/futex-wake.c:25:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> 37 | __kernel_old_time_t tv_sec; /* seconds */
> | ^~~~~~~~~~~~~~~~~~~
> make[3]: *** [/git/perf-5.16.0-rc4/tools/build/Makefile.build:139: bench] Error 2
> 11 114.27 alpine:3.13 : Ok gcc (Alpine 10.2.1_pre1) 10.2.1 20201203 , Alpine clang version 10.0.1
> 12 100.12 alpine:3.14 : Ok gcc (Alpine 10.3.1_git20210424) 10.3.1 20210424 , Alpine clang version 11.1.0
> 13 101.06 alpine:3.15 : Ok gcc (Alpine 10.3.1_git20211027) 10.3.1 20211027 , Alpine clang version 12.0.1
> 14 101.96 alpine:edge : Ok gcc (Alpine 11.2.1_git20211128) 11.2.1 20211128 , Alpine clang version 12.0.1
> 15 6.98 alt:p8 : FAIL gcc version 5.3.1 20151207 (ALT p8 5.3.1-alt3.M80P.1) (GCC)
> In file included from bench/futex-hash.c:29:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^
> In file included from bench/futex-wake.c:25:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^
> In file included from bench/futex-wake-parallel.c:31:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^
> make[3]: *** [bench] Error 2
> 16 73.65 alt:p9 : Ok x86_64-alt-linux-gcc (GCC) 8.4.1 20200305 (ALT p9 8.4.1-alt0.p9.1) , clang version 10.0.0
> 17 72.34 alt:sisyphus : Ok x86_64-alt-linux-gcc (GCC) 11.2.1 20210911 (ALT Sisyphus 11.2.1-alt1) , ALT Linux Team clang version 12.0.1
> 18 7.58 amazonlinux:1 : FAIL gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)
> In file included from bench/futex-hash.c:29:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^~~~~~~~~~~~~~~~~~~
> In file included from bench/futex-wake.c:25:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^~~~~~~~~~~~~~~~~~~
> make[3]: *** [bench] Error 2
> 19 8.28 amazonlinux:2 : FAIL gcc version 7.3.1 20180712 (Red Hat 7.3.1-13) (GCC)
> In file included from bench/futex-hash.c:29:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^~~~~~~~~~~~~~~~~~~
> make[3]: *** [bench] Error 2
> 20 79.16 centos:8 : Ok gcc (GCC) 8.4.1 20200928 (Red Hat 8.4.1-1) , clang version 11.0.1 (Red Hat 11.0.1-1.module_el8.4.0+966+2995ef20)
>
>
> Still building on the other containers.
Some more:
21 94.54 centos:stream : Ok gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-3) , clang version 12.0.1 (Red Hat 12.0.1-2.module_el8.6.0+937+1cafe22c)
22 48.51 clearlinux:latest : Ok gcc (Clear Linux OS for Intel Architecture) 11.2.1 20211202 releases/gcc-11.2.0-549-g2d5be1fca0 , clang version 11.1.0
23 7.38 debian:9 : FAIL gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
In file included from bench/futex-wake.c:25:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
In file included from bench/futex-hash.c:29:0:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
/git/perf-5.16.0-rc4/tools/build/Makefile.build:139: recipe for target 'bench' failed
make[3]: *** [bench] Error 2
24 7.08 debian:10 : FAIL gcc version 8.3.0 (Debian 8.3.0-6)
In file included from bench/futex-hash.c:29:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
In file included from bench/futex-wake.c:25:
bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
__kernel_old_time_t tv_sec; /* seconds */
^~~~~~~~~~~~~~~~~~~
make[3]: *** [/git/perf-5.16.0-rc4/tools/build/Makefile.build:139: bench] Error 2
25 79.95 debian:11 : Ok gcc (Debian 10.2.1-6) 10.2.1 20210110 , Debian clang version 11.0.1-2
On Fri, Dec 10, 2021 at 2:44 PM Arnaldo Carvalho de Melo
<[email protected]> wrote:
> Em Fri, Dec 10, 2021 at 10:36:30AM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Fri, Dec 10, 2021 at 09:58:52AM +1000, Alistair Francis escreveu:
> > > From: Alistair Francis <[email protected]>
> > >
> > > Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
> > > time_t and as such don't have the SYS_futex syscall. This patch will
> > > allow us to use the SYS_futex_time64 syscall on those platforms.
> > >
> > > This also converts the futex calls to be y2038 safe (when built for a
> > > 5.1+ kernel).
> > >
> > > This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
> > > "Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
> > >
> > > The original commit was reverted as including linux/time_types.h would
> > > fail to compile on older kernels. This commit doesn't include
> > > linux/time_types.h to avoid this issue.
> >
> > 10 9.99 alpine:3.12 : FAIL gcc version 9.3.0 (Alpine 9.3.0)
> > In file included from bench/futex-hash.c:29:
> > bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> > 37 | __kernel_old_time_t tv_sec; /* seconds */
> > | ^~~~~~~~~~~~~~~~~~~
> > In file included from bench/futex-wake.c:25:
It looks like we need to add include/uapi/linux/time_types.h to
tools/include/linux/ and update tools/include/linux/types.h
in order to address this.
Arnd
Em Fri, Dec 10, 2021 at 03:23:42PM +0100, Arnd Bergmann escreveu:
> On Fri, Dec 10, 2021 at 2:44 PM Arnaldo Carvalho de Melo
> <[email protected]> wrote:
> > Em Fri, Dec 10, 2021 at 10:36:30AM -0300, Arnaldo Carvalho de Melo escreveu:
> > > Em Fri, Dec 10, 2021 at 09:58:52AM +1000, Alistair Francis escreveu:
> > > > From: Alistair Francis <[email protected]>
> > > > Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
> > > > time_t and as such don't have the SYS_futex syscall. This patch will
> > > > allow us to use the SYS_futex_time64 syscall on those platforms.
> > > > This also converts the futex calls to be y2038 safe (when built for a
> > > > 5.1+ kernel).
> > > > This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
> > > > "Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
> > > > The original commit was reverted as including linux/time_types.h would
> > > > fail to compile on older kernels. This commit doesn't include
> > > > linux/time_types.h to avoid this issue.
> > > 10 9.99 alpine:3.12 : FAIL gcc version 9.3.0 (Alpine 9.3.0)
> > > In file included from bench/futex-hash.c:29:
> > > bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> > > 37 | __kernel_old_time_t tv_sec; /* seconds */
> > > | ^~~~~~~~~~~~~~~~~~~
> > > In file included from bench/futex-wake.c:25:
> It looks like we need to add include/uapi/linux/time_types.h to
> tools/include/linux/ and update tools/include/linux/types.h
> in order to address this.
And make sure it is found before the system ones, yes, that would fix
the issues. I'll try to do it these days.
- Arnaldo
On Fri, Dec 10, 2021 at 11:36 PM Arnaldo Carvalho de Melo
<[email protected]> wrote:
>
> Em Fri, Dec 10, 2021 at 09:58:52AM +1000, Alistair Francis escreveu:
> > From: Alistair Francis <[email protected]>
> >
> > Some 32-bit architectures (such are 32-bit RISC-V) only have a 64-bit
> > time_t and as such don't have the SYS_futex syscall. This patch will
> > allow us to use the SYS_futex_time64 syscall on those platforms.
> >
> > This also converts the futex calls to be y2038 safe (when built for a
> > 5.1+ kernel).
> >
> > This is a revert of commit ba4026b09d83acf56c040b6933eac7916c27e728
> > "Revert "perf bench futex: Add support for 32-bit systems with 64-bit time_t"".
> >
> > The original commit was reverted as including linux/time_types.h would
> > fail to compile on older kernels. This commit doesn't include
> > linux/time_types.h to avoid this issue.
>
> 10 9.99 alpine:3.12 : FAIL gcc version 9.3.0 (Alpine 9.3.0)
> In file included from bench/futex-hash.c:29:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> 37 | __kernel_old_time_t tv_sec; /* seconds */
> | ^~~~~~~~~~~~~~~~~~~
> In file included from bench/futex-wake.c:25:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> 37 | __kernel_old_time_t tv_sec; /* seconds */
> | ^~~~~~~~~~~~~~~~~~~
> make[3]: *** [/git/perf-5.16.0-rc4/tools/build/Makefile.build:139: bench] Error 2
> 11 114.27 alpine:3.13 : Ok gcc (Alpine 10.2.1_pre1) 10.2.1 20201203 , Alpine clang version 10.0.1
> 12 100.12 alpine:3.14 : Ok gcc (Alpine 10.3.1_git20210424) 10.3.1 20210424 , Alpine clang version 11.1.0
> 13 101.06 alpine:3.15 : Ok gcc (Alpine 10.3.1_git20211027) 10.3.1 20211027 , Alpine clang version 12.0.1
> 14 101.96 alpine:edge : Ok gcc (Alpine 11.2.1_git20211128) 11.2.1 20211128 , Alpine clang version 12.0.1
> 15 6.98 alt:p8 : FAIL gcc version 5.3.1 20151207 (ALT p8 5.3.1-alt3.M80P.1) (GCC)
> In file included from bench/futex-hash.c:29:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^
> In file included from bench/futex-wake.c:25:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^
> In file included from bench/futex-wake-parallel.c:31:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^
> make[3]: *** [bench] Error 2
> 16 73.65 alt:p9 : Ok x86_64-alt-linux-gcc (GCC) 8.4.1 20200305 (ALT p9 8.4.1-alt0.p9.1) , clang version 10.0.0
> 17 72.34 alt:sisyphus : Ok x86_64-alt-linux-gcc (GCC) 11.2.1 20210911 (ALT Sisyphus 11.2.1-alt1) , ALT Linux Team clang version 12.0.1
> 18 7.58 amazonlinux:1 : FAIL gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)
> In file included from bench/futex-hash.c:29:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^~~~~~~~~~~~~~~~~~~
> In file included from bench/futex-wake.c:25:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^~~~~~~~~~~~~~~~~~~
> make[3]: *** [bench] Error 2
> 19 8.28 amazonlinux:2 : FAIL gcc version 7.3.1 20180712 (Red Hat 7.3.1-13) (GCC)
> In file included from bench/futex-hash.c:29:0:
> bench/futex.h:37:2: error: unknown type name '__kernel_old_time_t'
> __kernel_old_time_t tv_sec; /* seconds */
> ^~~~~~~~~~~~~~~~~~~
> make[3]: *** [bench] Error 2
> 20 79.16 centos:8 : Ok gcc (GCC) 8.4.1 20200928 (Red Hat 8.4.1-1) , clang version 11.0.1 (Red Hat 11.0.1-1.module_el8.4.0+966+2995ef20)
Is there a way I can reproduce this failure?
Alistair
>
>
> Still building on the other containers.
>
> - Arnaldo