2021-10-15 09:57:01

by Alistair Francis

[permalink] [raw]
Subject: [PATCH v2 1/2] perf bench futex: Use a 64-bit time_t

From: Alistair Francis <[email protected]>

Convert tools/perf 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 us to build perf for 32-bit architectures with 64-bit time_t
like RISC-V 32-bit.

Signed-off-by: Alistair Francis <[email protected]>
---
tools/perf/bench/futex.h | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index b3853aac3021c..b9665d43d2988 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -12,6 +12,7 @@
#include <sys/syscall.h>
#include <sys/types.h>
#include <linux/futex.h>
+#include <linux/time_types.h>

struct bench_futex_parameters {
bool silent;
@@ -27,12 +28,14 @@ struct bench_futex_parameters {
unsigned int nrequeue;
};

+#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
@@ -47,15 +50,26 @@ struct bench_futex_parameters {
* 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

/**
* futex_wait() - block on uaddr with optional timeout
* @timeout: relative timeout
*/
static inline int
-futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
+futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec64 *timeout, int opflags)
{
return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
}
@@ -74,7 +88,7 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
* futex_lock_pi() - block on uaddr as a PI mutex
*/
static inline int
-futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
+futex_lock_pi(u_int32_t *uaddr, struct timespec64 *timeout, int opflags)
{
return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
}
@@ -111,7 +125,7 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
*/
static inline int
futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_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


2021-10-15 09:57:30

by Alistair Francis

[permalink] [raw]
Subject: [PATCH v2 2/2] selftests: futex: Use a 64-bit time_t

From: Alistair Francis <[email protected]>

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 <[email protected]>
---
.../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

2021-10-15 13:55:14

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] perf bench futex: Use a 64-bit time_t

On Fri, Oct 15, 2021 at 2:56 AM Alistair Francis
<[email protected]> wrote:
>
> From: Alistair Francis <[email protected]>
>
> Convert tools/perf 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 us to build perf for 32-bit architectures with 64-bit time_t
> like RISC-V 32-bit.
>
> Signed-off-by: Alistair Francis <[email protected]>

Reviewed-by: Arnd Bergmann <[email protected]>

2021-10-15 13:55:28

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] selftests: futex: Use a 64-bit time_t

On Fri, Oct 15, 2021 at 2:56 AM Alistair Francis
<[email protected]> wrote:
>
> From: Alistair Francis <[email protected]>
>
> 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 <[email protected]>

Reviewed-by: Arnd Bergmann <[email protected]>

2021-10-19 16:58:48

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] perf bench futex: Use a 64-bit time_t

Em Fri, Oct 15, 2021 at 10:56:33AM +1000, Alistair Francis escreveu:
> From: Alistair Francis <[email protected]>
>
> Convert tools/perf 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.

No, perf is not tied to the kernel, one can use a new perf tool on any
previous kernel, and an old perf tool should work on new kernels as
well.

- Arnaldo

> This allows us to build perf for 32-bit architectures with 64-bit time_t
> like RISC-V 32-bit.
>
> Signed-off-by: Alistair Francis <[email protected]>
> ---
> tools/perf/bench/futex.h | 26 ++++++++++++++++++++------
> 1 file changed, 20 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
> index b3853aac3021c..b9665d43d2988 100644
> --- a/tools/perf/bench/futex.h
> +++ b/tools/perf/bench/futex.h
> @@ -12,6 +12,7 @@
> #include <sys/syscall.h>
> #include <sys/types.h>
> #include <linux/futex.h>
> +#include <linux/time_types.h>
>
> struct bench_futex_parameters {
> bool silent;
> @@ -27,12 +28,14 @@ struct bench_futex_parameters {
> unsigned int nrequeue;
> };
>
> +#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
> @@ -47,15 +50,26 @@ struct bench_futex_parameters {
> * 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
>
> /**
> * futex_wait() - block on uaddr with optional timeout
> * @timeout: relative timeout
> */
> static inline int
> -futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
> +futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec64 *timeout, int opflags)
> {
> return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
> }
> @@ -74,7 +88,7 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
> * futex_lock_pi() - block on uaddr as a PI mutex
> */
> static inline int
> -futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
> +futex_lock_pi(u_int32_t *uaddr, struct timespec64 *timeout, int opflags)
> {
> return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
> }
> @@ -111,7 +125,7 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
> */
> static inline int
> futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_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

--

- Arnaldo

2021-10-19 23:20:45

by Alistair Francis

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] perf bench futex: Use a 64-bit time_t

On Wed, Oct 20, 2021 at 2:56 AM Arnaldo Carvalho de Melo
<[email protected]> wrote:
>
> Em Fri, Oct 15, 2021 at 10:56:33AM +1000, Alistair Francis escreveu:
> > From: Alistair Francis <[email protected]>
> >
> > Convert tools/perf 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.
>
> No, perf is not tied to the kernel, one can use a new perf tool on any
> previous kernel, and an old perf tool should work on new kernels as
> well.

+ André, I won't be doing this the way you requested

Ok, so back to the previous version then. I'll send the patches soon.

Alistair

>
> - Arnaldo
>
> > This allows us to build perf for 32-bit architectures with 64-bit time_t
> > like RISC-V 32-bit.
> >
> > Signed-off-by: Alistair Francis <[email protected]>
> > ---
> > tools/perf/bench/futex.h | 26 ++++++++++++++++++++------
> > 1 file changed, 20 insertions(+), 6 deletions(-)
> >
> > diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
> > index b3853aac3021c..b9665d43d2988 100644
> > --- a/tools/perf/bench/futex.h
> > +++ b/tools/perf/bench/futex.h
> > @@ -12,6 +12,7 @@
> > #include <sys/syscall.h>
> > #include <sys/types.h>
> > #include <linux/futex.h>
> > +#include <linux/time_types.h>
> >
> > struct bench_futex_parameters {
> > bool silent;
> > @@ -27,12 +28,14 @@ struct bench_futex_parameters {
> > unsigned int nrequeue;
> > };
> >
> > +#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
> > @@ -47,15 +50,26 @@ struct bench_futex_parameters {
> > * 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
> >
> > /**
> > * futex_wait() - block on uaddr with optional timeout
> > * @timeout: relative timeout
> > */
> > static inline int
> > -futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
> > +futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec64 *timeout, int opflags)
> > {
> > return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
> > }
> > @@ -74,7 +88,7 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
> > * futex_lock_pi() - block on uaddr as a PI mutex
> > */
> > static inline int
> > -futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
> > +futex_lock_pi(u_int32_t *uaddr, struct timespec64 *timeout, int opflags)
> > {
> > return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
> > }
> > @@ -111,7 +125,7 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
> > */
> > static inline int
> > futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_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
>
> --
>
> - Arnaldo

2021-10-20 00:04:12

by André Almeida

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] perf bench futex: Use a 64-bit time_t

Às 20:17 de 19/10/21, Alistair Francis escreveu:
> On Wed, Oct 20, 2021 at 2:56 AM Arnaldo Carvalho de Melo
> <[email protected]> wrote:
>>
>> Em Fri, Oct 15, 2021 at 10:56:33AM +1000, Alistair Francis escreveu:
>>> From: Alistair Francis <[email protected]>
>>>
>>> Convert tools/perf 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.
>>
>> No, perf is not tied to the kernel, one can use a new perf tool on any
>> previous kernel, and an old perf tool should work on new kernels as
>> well.
>
> + André, I won't be doing this the way you requested
>

Ok, thanks anyway for your work and sorry for the trouble :)

> Ok, so back to the previous version then. I'll send the patches soon.
>
> Alistair
>
>>
>> - Arnaldo
>>
>>> This allows us to build perf for 32-bit architectures with 64-bit time_t
>>> like RISC-V 32-bit.
>>>
>>> Signed-off-by: Alistair Francis <[email protected]>
>>> ---
>>> tools/perf/bench/futex.h | 26 ++++++++++++++++++++------
>>> 1 file changed, 20 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
>>> index b3853aac3021c..b9665d43d2988 100644
>>> --- a/tools/perf/bench/futex.h
>>> +++ b/tools/perf/bench/futex.h
>>> @@ -12,6 +12,7 @@
>>> #include <sys/syscall.h>
>>> #include <sys/types.h>
>>> #include <linux/futex.h>
>>> +#include <linux/time_types.h>
>>>
>>> struct bench_futex_parameters {
>>> bool silent;
>>> @@ -27,12 +28,14 @@ struct bench_futex_parameters {
>>> unsigned int nrequeue;
>>> };
>>>
>>> +#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
>>> @@ -47,15 +50,26 @@ struct bench_futex_parameters {
>>> * 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
>>>
>>> /**
>>> * futex_wait() - block on uaddr with optional timeout
>>> * @timeout: relative timeout
>>> */
>>> static inline int
>>> -futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
>>> +futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec64 *timeout, int opflags)
>>> {
>>> return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
>>> }
>>> @@ -74,7 +88,7 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
>>> * futex_lock_pi() - block on uaddr as a PI mutex
>>> */
>>> static inline int
>>> -futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
>>> +futex_lock_pi(u_int32_t *uaddr, struct timespec64 *timeout, int opflags)
>>> {
>>> return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
>>> }
>>> @@ -111,7 +125,7 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
>>> */
>>> static inline int
>>> futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_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
>>
>> --
>>
>> - Arnaldo

2021-10-20 02:01:26

by Alistair Francis

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] perf bench futex: Use a 64-bit time_t

On Wed, Oct 20, 2021 at 10:01 AM André Almeida
<[email protected]> wrote:
>
> Às 20:17 de 19/10/21, Alistair Francis escreveu:
> > On Wed, Oct 20, 2021 at 2:56 AM Arnaldo Carvalho de Melo
> > <[email protected]> wrote:
> >>
> >> Em Fri, Oct 15, 2021 at 10:56:33AM +1000, Alistair Francis escreveu:
> >>> From: Alistair Francis <[email protected]>
> >>>
> >>> Convert tools/perf 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.
> >>
> >> No, perf is not tied to the kernel, one can use a new perf tool on any
> >> previous kernel, and an old perf tool should work on new kernels as
> >> well.
> >
> > + André, I won't be doing this the way you requested
> >
>
> Ok, thanks anyway for your work and sorry for the trouble :)

No worries!

Alistair