linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] perf benchmark: Call the futex syscall from a function
@ 2021-09-10  4:31 Alistair Francis
  2021-09-10  4:31 ` [PATCH v2 2/2] perf bench: Add support for 32-bit systems with 64-bit time_t Alistair Francis
  0 siblings, 1 reply; 3+ messages in thread
From: Alistair Francis @ 2021-09-10  4:31 UTC (permalink / raw)
  To: linux-riscv, linux-perf-users
  Cc: linux-kernel, alistair23, namhyung, jolsa, alexander.shishkin,
	mark.rutland, acme, dave, dvhart, peterz, mingo, tglx,
	atish.patra, arnd, Alistair Francis

From: Alistair Francis <alistair.francis@wdc.com>

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 <alistair.francis@wdc.com>
---
 tools/perf/bench/futex.h | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index b3853aac3021c..f80a4759ee79b 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -28,7 +28,7 @@ struct bench_futex_parameters {
 };
 
 /**
- * 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
@@ -38,17 +38,26 @@ struct bench_futex_parameters {
  * @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(u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout,
+	u_int32_t *uaddr2, int val3, int opflags)
+{
+	return syscall(SYS_futex, uaddr, op | opflags, val, ts32, uaddr2, val3);
+}
+
+static inline int
+futex_syscall_nr_requeue(u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue,
+	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
@@ -57,7 +66,7 @@ struct bench_futex_parameters {
 static inline int
 futex_wait(u_int32_t *uaddr, u_int32_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);
 }
 
 /**
@@ -67,7 +76,7 @@ futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflag
 static inline int
 futex_wake(u_int32_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);
 }
 
 /**
@@ -76,7 +85,7 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
 static inline int
 futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
 {
-	return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
+	return futex_syscall(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
 }
 
 /**
@@ -85,7 +94,7 @@ futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
 static inline int
 futex_unlock_pi(u_int32_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);
 }
 
 /**
@@ -97,7 +106,7 @@ static inline int
 futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wake,
 		 int nr_requeue, int opflags)
 {
-	return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
+	return futex_syscall_nr_requeue(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
 		 val, opflags);
 }
 
@@ -113,7 +122,7 @@ static inline int
 futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2,
 		      struct timespec *timeout, int opflags)
 {
-	return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
+	return futex_syscall(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
 		     opflags);
 }
 
@@ -130,7 +139,7 @@ static inline int
 futex_cmp_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2,
 		     int nr_requeue, int opflags)
 {
-	return futex(uaddr, FUTEX_CMP_REQUEUE_PI, 1, nr_requeue, uaddr2,
+	return futex_syscall_nr_requeue(uaddr, FUTEX_CMP_REQUEUE_PI, 1, nr_requeue, uaddr2,
 		     val, opflags);
 }
 
-- 
2.31.1


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

* [PATCH v2 2/2] perf bench: Add support for 32-bit systems with 64-bit time_t
  2021-09-10  4:31 [PATCH v2 1/2] perf benchmark: Call the futex syscall from a function Alistair Francis
@ 2021-09-10  4:31 ` Alistair Francis
  2021-09-10  7:17   ` Arnd Bergmann
  0 siblings, 1 reply; 3+ messages in thread
From: Alistair Francis @ 2021-09-10  4:31 UTC (permalink / raw)
  To: linux-riscv, linux-perf-users
  Cc: linux-kernel, alistair23, namhyung, jolsa, alexander.shishkin,
	mark.rutland, acme, dave, dvhart, peterz, mingo, tglx,
	atish.patra, arnd, Alistair Francis

From: Alistair Francis <alistair.francis@wdc.com>

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.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 tools/perf/bench/futex.h | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index f80a4759ee79b..09c5596726c60 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -27,6 +27,12 @@ struct bench_futex_parameters {
 	unsigned int nrequeue;
 };
 
+/* A version of 'struct timespec' with 32-bit time_t and nanoseconds.  */
+struct __timespec32 {
+	__kernel_long_t tv_sec;
+	__kernel_long_t tv_nsec;
+};
+
 /**
  * futex_syscall() - SYS_futex syscall wrapper
  * @uaddr:	address of first futex
@@ -49,14 +55,49 @@ static inline int
 futex_syscall(u_int32_t *uaddr, int op, u_int32_t val, struct timespec *timeout,
 	u_int32_t *uaddr2, int val3, int opflags)
 {
-	return syscall(SYS_futex, uaddr, op | opflags, val, ts32, uaddr2, val3);
+#if defined(SYS_futex_time64)
+	if (sizeof(*timeout) != sizeof(struct __timespec32)) {
+		int ret =  syscall(SYS_futex_time64, uaddr, op | opflags, val, timeout,
+				   uaddr2, val3);
+	if (ret == 0 || errno != ENOSYS)
+		return ret;
+	}
+#endif
+
+#if defined(SYS_futex)
+	if (sizeof(*timeout) == sizeof(struct __timespec32))
+		return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
+
+	if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
+		struct __timespec32 ts32;
+
+		ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
+		ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
+
+		return syscall(SYS_futex, uaddr, op | opflags, val, ts32, uaddr2, val3);
+	} else if (!timeout) {
+		return syscall(SYS_futex, uaddr, op | opflags, val, NULL, uaddr2, val3);
+	}
+#endif
+
+	errno = ENOSYS;
+	return -1;
 }
 
 static inline int
 futex_syscall_nr_requeue(u_int32_t *uaddr, int op, u_int32_t val, int nr_requeue,
 	u_int32_t *uaddr2, int val3, int opflags)
 {
+#if defined(SYS_futex_time64)
+	int ret =  syscall(SYS_futex_time64, uaddr, op | opflags, val, nr_requeue,
+			   uaddr2, val3);
+	if (ret == 0 || errno != ENOSYS)
+		return ret;
+#endif
+
+#if defined(SYS_futex)
 	return syscall(SYS_futex, uaddr, op | opflags, val, nr_requeue, uaddr2, val3);
+#endif
 }
 
 /**
-- 
2.31.1


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

* Re: [PATCH v2 2/2] perf bench: Add support for 32-bit systems with 64-bit time_t
  2021-09-10  4:31 ` [PATCH v2 2/2] perf bench: Add support for 32-bit systems with 64-bit time_t Alistair Francis
@ 2021-09-10  7:17   ` Arnd Bergmann
  0 siblings, 0 replies; 3+ messages in thread
From: Arnd Bergmann @ 2021-09-10  7:17 UTC (permalink / raw)
  To: Alistair Francis
  Cc: linux-riscv, linux-perf-users, Linux Kernel Mailing List,
	Alistair Francis, Namhyung Kim, Jiri Olsa, Alexander Shishkin,
	Mark Rutland, Arnaldo Carvalho de Melo, Davidlohr Bueso,
	Darren Hart, Peter Zijlstra, Ingo Molnar, Thomas Gleixner,
	Atish Patra, Arnd Bergmann, Alistair Francis

On Fri, Sep 10, 2021 at 6:31 AM Alistair Francis
<alistair.francis@opensource.wdc.com> wrote:
>
> From: Alistair Francis <alistair.francis@wdc.com>
>
> 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.
>
> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  tools/perf/bench/futex.h | 43 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
> index f80a4759ee79b..09c5596726c60 100644
> --- a/tools/perf/bench/futex.h
> +++ b/tools/perf/bench/futex.h
> @@ -27,6 +27,12 @@ struct bench_futex_parameters {
>         unsigned int nrequeue;
>  };
>
> +/* A version of 'struct timespec' with 32-bit time_t and nanoseconds.  */
> +struct __timespec32 {
> +       __kernel_long_t tv_sec;
> +       __kernel_long_t tv_nsec;
> +};

Why not use the existing __kernel_old_timespec structure definition
from the header?

> +#if defined(SYS_futex)
> +       if (sizeof(*timeout) == sizeof(struct __timespec32))
> +               return syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
> +
> +       if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
> +               struct __timespec32 ts32;
> +
> +               ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
> +               ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
> +
> +               return syscall(SYS_futex, uaddr, op | opflags, val, ts32, uaddr2, val3);
> +       } else if (!timeout) {
> +               return syscall(SYS_futex, uaddr, op | opflags, val, NULL, uaddr2, val3);
> +       }
> +#endif
> +
> +       errno = ENOSYS;
> +       return -1;

Similarly, I think just using the kernel's constants like __NR_futex instead of
SYS_futex would be more appropriate here, this way you know if futex_time64
is available and don't have to do the emulation for running the binary
on pre-5.1
kernels. Perf already uses __NR_perf_event_open, __NR_getcpu, and
__NR_setns instead of the SYS_* versions.

         Arnd

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

end of thread, other threads:[~2021-09-10  7:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-10  4:31 [PATCH v2 1/2] perf benchmark: Call the futex syscall from a function Alistair Francis
2021-09-10  4:31 ` [PATCH v2 2/2] perf bench: Add support for 32-bit systems with 64-bit time_t Alistair Francis
2021-09-10  7:17   ` Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).