* [PATCH 1/8] perf bench futex: Retry futex_wait() when interrupted by a signal
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 2/8] perf bench futex: Set the number of hash buckets in futex wake Michal Pluta
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
The worker threads in 'futex wake' and 'futex wake-parallel' are meant
to go back to sleep when a signal interrupts futex_wait(), but the check
never works. futex_wait() returns -1 and sets errno, so comparing its
return value with EINTR is always true and the loop ends at the first
interruption.
The worker then exits without having been woken. 'futex wake' keeps
calling futex_wake() forever, because the number of woken threads never
reaches the total, while 'futex wake-parallel' finishes but shows the
wrong number of threads.
Check errno instead.
Fixes: 598adc5c9c1c ("perf bench futex: Handle spurious wakeups")
Fixes: d65817b4e707 ("perf bench futex: Support parallel waker threads")
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-wake-parallel.c | 7 +++----
tools/perf/bench/futex-wake.c | 7 +++----
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 6aede7c46b33..a089d8ee4b02 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -139,10 +139,9 @@ static void *blocked_workerfn(void *arg __maybe_unused)
cond_wait(&thread_worker, &thread_lock);
mutex_unlock(&thread_lock);
- while (1) { /* handle spurious wakeups */
- if (futex_wait(&futex, 0, NULL, futex_flag) != EINTR)
- break;
- }
+ /* Retry if the wait was interrupted by a signal. */
+ while (futex_wait(&futex, 0, NULL, futex_flag) == -1 && errno == EINTR)
+ ;
pthread_exit(NULL);
return NULL;
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index a31fc1563862..66d30ca91405 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -75,10 +75,9 @@ static void *workerfn(void *arg __maybe_unused)
cond_wait(&thread_worker, &thread_lock);
mutex_unlock(&thread_lock);
- while (1) {
- if (futex_wait(&futex1, 0, NULL, futex_flag) != EINTR)
- break;
- }
+ /* Retry if the wait was interrupted by a signal. */
+ while (futex_wait(&futex1, 0, NULL, futex_flag) == -1 && errno == EINTR)
+ ;
pthread_exit(NULL);
return NULL;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 2/8] perf bench futex: Set the number of hash buckets in futex wake
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
2026-09-26 19:04 ` [PATCH 1/8] perf bench futex: Retry futex_wait() when interrupted by a signal Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 3/8] perf bench futex: Use the whole timeval for elapsed times Michal Pluta
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
'perf bench futex wake -b N' fails unless N happens to be the number of
buckets the kernel is already using:
$ perf bench futex wake -b 128
Requested number of hash buckets does not currently used.
Requested: 128 in usage: 64
perf: prctl(PR_FUTEX_HASH): No such file or directory
The other futex benchmarks call futex_set_nbuckets_param() to ask the
kernel for the requested size, but 'futex wake' only checks afterwards
which size is in use, so the request never reaches the kernel. The call
now happens before the run summary, as in the other benchmarks.
Fixes: 60035a3981a7 ("tools/perf: Allow to select the number of hash buckets")
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-wake.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 66d30ca91405..58427bb55c03 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -175,6 +175,8 @@ int bench_futex_wake(int argc, const char **argv)
if (!params.fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
+ futex_set_nbuckets_param(¶ms);
+
printf("Run summary [PID %d]: blocking on %d threads (at [%s] futex %p), "
"waking up %d at a time.\n\n",
getpid(), params.nthreads, params.fshared ? "shared":"private",
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 3/8] perf bench futex: Use the whole timeval for elapsed times
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
2026-09-26 19:04 ` [PATCH 1/8] perf bench futex: Retry futex_wait() when interrupted by a signal Michal Pluta
2026-09-26 19:04 ` [PATCH 2/8] perf bench futex: Set the number of hash buckets in futex wake Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 4/8] perf bench futex: Reject invalid -q, -f and -b values Michal Pluta
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
Several futex benchmarks read only one field of the struct timeval that
timersub() produces, so part of the elapsed time is lost.
'futex wake', 'futex wake-parallel' and 'futex requeue' print tv_usec,
so a run that takes 1.5 s is shown as 500 ms. 'futex hash' and 'futex
lock-pi' divide their operation count by tv_sec, which overstates the
throughput when a run is stopped early, and gives 0 if that happens
within the first second. Their "total secs" is truncated in the same
way.
Use the whole timeval and print "total secs" with two decimals. With
--runtime=0 the rate is now computed over the time that actually
elapsed, instead of showing 0.
Fixes: 27db78307481 ("perf bench: Add futex-wake microbenchmark")
Fixes: 0fb298cf95c0 ("perf bench: Add futex-requeue microbenchmark")
Fixes: a043971141f1 ("perf bench: Add futex-hash microbenchmark")
Fixes: d2f3f5d2e9ca ("perf bench futex: Add lock_pi stresser")
Fixes: d65817b4e707 ("perf bench futex: Support parallel waker threads")
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-hash.c | 12 ++++++++----
tools/perf/bench/futex-lock-pi.c | 12 ++++++++----
tools/perf/bench/futex-requeue.c | 8 +++++---
tools/perf/bench/futex-wake-parallel.c | 8 ++++++--
tools/perf/bench/futex-wake.c | 6 ++++--
5 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 7e29f04da744..32b88df8ee6d 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
+#include <linux/time64.h>
#include <linux/zalloc.h>
#include <sys/time.h>
#include <sys/mman.h>
@@ -118,18 +119,19 @@ static void print_summary(void)
unsigned long avg = avg_stats(&throughput_stats);
double stddev = stddev_stats(&throughput_stats);
- printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
+ printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %.2f\n",
!params.silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
- (int)bench__runtime.tv_sec);
+ bench__runtime.tv_sec + bench__runtime.tv_usec / (double)USEC_PER_SEC);
futex_print_nbuckets(¶ms);
}
int bench_futex_hash(int argc, const char **argv)
{
int ret = 0;
cpu_set_t *cpuset;
struct sigaction act;
unsigned int i;
+ u64 runtime_us;
pthread_attr_t thread_attr;
struct worker *worker = NULL;
struct perf_cpu_map *cpu;
@@ -229,9 +231,11 @@ int bench_futex_hash(int argc, const char **argv)
cond_destroy(&thread_worker);
mutex_destroy(&thread_lock);
+ runtime_us = (u64)bench__runtime.tv_sec * USEC_PER_SEC + bench__runtime.tv_usec;
+
for (i = 0; i < params.nthreads; i++) {
- unsigned long t = bench__runtime.tv_sec > 0 ?
- worker[i].ops / bench__runtime.tv_sec : 0;
+ unsigned long t = runtime_us ?
+ (u64)worker[i].ops * USEC_PER_SEC / runtime_us : 0;
update_stats(&throughput_stats, t);
if (!params.silent) {
if (params.nfutexes == 1)
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 40640b674427..7190f5102e09 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -13,6 +13,7 @@
#include <subcmd/parse-options.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
+#include <linux/time64.h>
#include <linux/zalloc.h>
#include <errno.h>
#include <perf/cpumap.h>
@@ -66,9 +67,9 @@ static void print_summary(void)
unsigned long avg = avg_stats(&throughput_stats);
double stddev = stddev_stats(&throughput_stats);
- printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
+ printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %.2f\n",
!params.silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
- (int)bench__runtime.tv_sec);
+ bench__runtime.tv_sec + bench__runtime.tv_usec / (double)USEC_PER_SEC);
futex_print_nbuckets(¶ms);
}
@@ -168,6 +169,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
{
int ret = 0;
unsigned int i;
+ u64 runtime_us;
struct sigaction act;
struct perf_cpu_map *cpu;
@@ -233,9 +235,11 @@ int bench_futex_lock_pi(int argc, const char **argv)
cond_destroy(&thread_worker);
mutex_destroy(&thread_lock);
+ runtime_us = (u64)bench__runtime.tv_sec * USEC_PER_SEC + bench__runtime.tv_usec;
+
for (i = 0; i < params.nthreads; i++) {
- unsigned long t = bench__runtime.tv_sec > 0 ?
- worker[i].ops / bench__runtime.tv_sec : 0;
+ unsigned long t = runtime_us ?
+ (u64)worker[i].ops * USEC_PER_SEC / runtime_us : 0;
update_stats(&throughput_stats, t);
if (!params.silent)
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 0748b0fd689e..5d4708f40c60 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -223,6 +223,7 @@ int bench_futex_requeue(int argc, const char **argv)
for (j = 0; j < bench_repeat && !done; j++) {
unsigned int nrequeued = 0, wakeups = 0;
struct timeval start, end, runtime;
+ u64 runtime_us;
/* create, launch & block all threads */
block_threads(worker, cpu);
@@ -267,23 +268,24 @@ int bench_futex_requeue(int argc, const char **argv)
gettimeofday(&end, NULL);
timersub(&end, &start, &runtime);
+ runtime_us = (u64)runtime.tv_sec * USEC_PER_SEC + runtime.tv_usec;
update_stats(&requeued_stats, nrequeued);
- update_stats(&requeuetime_stats, runtime.tv_usec);
+ update_stats(&requeuetime_stats, runtime_us);
if (!params.silent) {
if (!params.pi)
printf("[Run %d]: Requeued %d of %d threads in "
"%.4f ms\n", j + 1, nrequeued,
params.nthreads,
- runtime.tv_usec / (double)USEC_PER_MSEC);
+ runtime_us / (double)USEC_PER_MSEC);
else {
nrequeued -= wakeups;
printf("[Run %d]: Awoke and Requeued (%d+%d) of "
"%d threads in %.4f ms\n",
j + 1, wakeups, nrequeued,
params.nthreads,
- runtime.tv_usec / (double)USEC_PER_MSEC);
+ runtime_us / (double)USEC_PER_MSEC);
}
}
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index a089d8ee4b02..fa70b7d4b473 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -192,7 +192,9 @@ static void print_run(struct thread_data *waking_worker, unsigned int run_num)
init_stats(&__waketime_stats);
for (i = 0; i < params.nwakes; i++) {
- update_stats(&__waketime_stats, waking_worker[i].runtime.tv_usec);
+ update_stats(&__waketime_stats,
+ (u64)waking_worker[i].runtime.tv_sec * USEC_PER_SEC +
+ waking_worker[i].runtime.tv_usec);
update_stats(&__wakeup_stats, waking_worker[i].nwoken);
}
@@ -229,7 +231,9 @@ static void do_run_stats(struct thread_data *waking_worker)
unsigned int i;
for (i = 0; i < params.nwakes; i++) {
- update_stats(&waketime_stats, waking_worker[i].runtime.tv_usec);
+ update_stats(&waketime_stats,
+ (u64)waking_worker[i].runtime.tv_sec * USEC_PER_SEC +
+ waking_worker[i].runtime.tv_usec);
update_stats(&wakeup_stats, waking_worker[i].nwoken);
}
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 58427bb55c03..12a75be077a0 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -191,6 +191,7 @@ int bench_futex_wake(int argc, const char **argv)
for (j = 0; j < bench_repeat && !done; j++) {
unsigned int nwoken = 0;
struct timeval start, end, runtime;
+ u64 runtime_us;
/* create, launch & block all threads */
block_threads(worker, cpu);
@@ -211,14 +212,15 @@ int bench_futex_wake(int argc, const char **argv)
params.nwakes, futex_flag);
gettimeofday(&end, NULL);
timersub(&end, &start, &runtime);
+ runtime_us = (u64)runtime.tv_sec * USEC_PER_SEC + runtime.tv_usec;
update_stats(&wakeup_stats, nwoken);
- update_stats(&waketime_stats, runtime.tv_usec);
+ update_stats(&waketime_stats, runtime_us);
if (!params.silent) {
printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
j + 1, nwoken, params.nthreads,
- runtime.tv_usec / (double)USEC_PER_MSEC);
+ runtime_us / (double)USEC_PER_MSEC);
}
for (i = 0; i < params.nthreads; i++) {
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 4/8] perf bench futex: Reject invalid -q, -f and -b values
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
` (2 preceding siblings ...)
2026-09-26 19:04 ` [PATCH 3/8] perf bench futex: Use the whole timeval for elapsed times Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 5/8] perf bench futex: Stop when futex_wake() fails in futex wake Michal Pluta
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
Some values make a futex benchmark hang or are silently ignored.
'futex requeue -q 0' never finishes, because no thread is requeued.
'futex hash -f 0' never finishes either, because with no futexes the
workers never notice that the run is over. A negative -b is treated as
if it had not been given, and the kernel simply auto-sizes the hash.
Print an error for these values, except for -b -1, which still means
automatic sizing.
Fixes: 0fb298cf95c0 ("perf bench: Add futex-requeue microbenchmark")
Fixes: a043971141f1 ("perf bench: Add futex-hash microbenchmark")
Fixes: 60035a3981a7 ("tools/perf: Allow to select the number of hash buckets")
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-hash.c | 3 +++
tools/perf/bench/futex-requeue.c | 4 ++++
tools/perf/bench/futex.c | 3 +++
3 files changed, 10 insertions(+)
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 32b88df8ee6d..710c253cfe17 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -161,6 +161,9 @@ int bench_futex_hash(int argc, const char **argv)
if (!params.nthreads) /* default to the number of CPUs */
params.nthreads = perf_cpu_map__nr(cpu);
+ if (!params.nfutexes)
+ errx(EXIT_FAILURE, "-f/--futexes must be at least 1");
+
worker = calloc(params.nthreads, sizeof(*worker));
if (!worker)
goto errmem;
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 5d4708f40c60..bc6efc2ecadb 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -207,6 +207,10 @@ int bench_futex_requeue(int argc, const char **argv)
if (params.broadcast)
params.nrequeue = params.nthreads;
+ /* A regular requeue that moves no threads would never finish. */
+ if (!params.pi && !params.nrequeue)
+ errx(EXIT_FAILURE, "-q/--nrequeue must be at least 1");
+
futex_set_nbuckets_param(¶ms);
printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %s%p), "
diff --git a/tools/perf/bench/futex.c b/tools/perf/bench/futex.c
index 1968c9d00b5b..5757d47f8f7c 100644
--- a/tools/perf/bench/futex.c
+++ b/tools/perf/bench/futex.c
@@ -17,6 +17,9 @@ void futex_set_nbuckets_param(struct bench_futex_parameters *params)
{
int ret;
+ if (params->nbuckets < -1)
+ errx(EXIT_FAILURE, "-b/--buckets must be -1 (auto), 0 or more");
+
if (params->nbuckets < 0)
return;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 5/8] perf bench futex: Stop when futex_wake() fails in futex wake
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
` (3 preceding siblings ...)
2026-09-26 19:04 ` [PATCH 4/8] perf bench futex: Reject invalid -q, -f and -b values Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 6/8] perf bench futex: Use a 64-bit operation counter in hash and lock-pi Michal Pluta
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
If futex_wake() fails, 'futex wake' adds -1 to its unsigned counter of
woken threads and retries forever. Exit with an error instead, as
'futex requeue' already does.
Fixes: 27db78307481 ("perf bench: Add futex-wake microbenchmark")
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-wake.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 12a75be077a0..7674622639ca 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -207,9 +207,14 @@ int bench_futex_wake(int argc, const char **argv)
/* Ok, all threads are patiently blocked, start waking folks up */
gettimeofday(&start, NULL);
- while (nwoken != params.nthreads)
- nwoken += futex_wake(&futex1,
- params.nwakes, futex_flag);
+ while (nwoken != params.nthreads) {
+ int r = futex_wake(&futex1, params.nwakes, futex_flag);
+
+ if (r < 0)
+ err(EXIT_FAILURE, "couldn't wakeup from %p", &futex1);
+
+ nwoken += r;
+ }
gettimeofday(&end, NULL);
timersub(&end, &start, &runtime);
runtime_us = (u64)runtime.tv_sec * USEC_PER_SEC + runtime.tv_usec;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 6/8] perf bench futex: Use a 64-bit operation counter in hash and lock-pi
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
` (4 preceding siblings ...)
2026-09-26 19:04 ` [PATCH 5/8] perf bench futex: Stop when futex_wake() fails in futex wake Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 7/8] perf bench futex: Clean up two nits in futex hash Michal Pluta
2026-09-26 19:04 ` [PATCH 8/8] perf bench futex: Fix wording in futex bench messages Michal Pluta
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
The per-thread operation counters in 'futex hash' and 'futex lock-pi'
are unsigned longs, which could overflow on 32-bit systems. Use u64
instead.
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-hash.c | 6 +++---
tools/perf/bench/futex-lock-pi.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 710c253cfe17..e18d98664d27 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -46,7 +46,7 @@ struct worker {
int tid;
u_int32_t *futex;
pthread_t thread;
- unsigned long ops;
+ u64 ops;
};
static struct bench_futex_parameters params = {
@@ -76,7 +76,7 @@ static void *workerfn(void *arg)
int ret;
struct worker *w = (struct worker *) arg;
unsigned int i;
- unsigned long ops = w->ops; /* avoid cacheline bouncing */
+ u64 ops = w->ops; /* avoid cacheline bouncing */
mutex_lock(&thread_lock);
threads_starting--;
@@ -238,7 +238,7 @@ int bench_futex_hash(int argc, const char **argv)
for (i = 0; i < params.nthreads; i++) {
unsigned long t = runtime_us ?
- (u64)worker[i].ops * USEC_PER_SEC / runtime_us : 0;
+ worker[i].ops * USEC_PER_SEC / runtime_us : 0;
update_stats(&throughput_stats, t);
if (!params.silent) {
if (params.nfutexes == 1)
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 7190f5102e09..8016a31b198d 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -29,7 +29,7 @@ struct worker {
int tid;
u_int32_t *futex;
pthread_t thread;
- unsigned long ops;
+ u64 ops;
};
static u_int32_t global_futex = 0;
@@ -86,7 +86,7 @@ static void toggle_done(int sig __maybe_unused,
static void *workerfn(void *arg)
{
struct worker *w = (struct worker *) arg;
- unsigned long ops = w->ops;
+ u64 ops = w->ops;
mutex_lock(&thread_lock);
threads_starting--;
@@ -239,7 +239,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
for (i = 0; i < params.nthreads; i++) {
unsigned long t = runtime_us ?
- (u64)worker[i].ops * USEC_PER_SEC / runtime_us : 0;
+ worker[i].ops * USEC_PER_SEC / runtime_us : 0;
update_stats(&throughput_stats, t);
if (!params.silent)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 7/8] perf bench futex: Clean up two nits in futex hash
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
` (5 preceding siblings ...)
2026-09-26 19:04 ` [PATCH 6/8] perf bench futex: Use a 64-bit operation counter in hash and lock-pi Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
2026-09-26 19:04 ` [PATCH 8/8] perf bench futex: Fix wording in futex bench messages Michal Pluta
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
The worker's check for an unexpected futex_wait() result tests
'errno != EAGAIN || errno != EWOULDBLOCK', which only works because the
two are equal, so use '&&' instead.
The CPU map is reference counted, so release it with perf_cpu_map__put()
instead of free().
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-hash.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index e18d98664d27..6f4af1a52d1b 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -95,7 +95,7 @@ static void *workerfn(void *arg)
*/
ret = futex_wait(&w->futex[i], 1234, NULL, futex_flag);
if (!params.silent &&
- (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
+ (!ret || (errno != EAGAIN && errno != EWOULDBLOCK)))
warn("Non-expected futex return call");
}
} while (!done);
@@ -256,7 +256,7 @@ int bench_futex_hash(int argc, const char **argv)
print_summary();
free(worker);
- free(cpu);
+ perf_cpu_map__put(cpu);
return ret;
errmem:
err(EXIT_FAILURE, "calloc");
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 8/8] perf bench futex: Fix wording in futex bench messages
2026-09-26 19:03 [PATCH 0/8] perf bench futex: Fix several bugs and bad inputs Michal Pluta
` (6 preceding siblings ...)
2026-09-26 19:04 ` [PATCH 7/8] perf bench futex: Clean up two nits in futex hash Michal Pluta
@ 2026-09-26 19:04 ` Michal Pluta
7 siblings, 0 replies; 9+ messages in thread
From: Michal Pluta @ 2026-09-26 19:04 UTC (permalink / raw)
To: acme, namhyung
Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Darren Hart,
Davidlohr Bueso, André Almeida, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Sebastian Andrzej Siewior, linux-kernel,
linux-perf-users
When the kernel is using a different number of hash buckets than
requested with -b, the message printed is ungrammatical, and it ends
with a stale errno even though nothing failed:
Requested number of hash buckets does not currently used.
Requested: 3 in usage: 64
perf: prctl(PR_FUTEX_HASH): No such file or directory
Fix the wording and use errx(), so that no errno text is printed:
Requested number of buckets differs from the number in use.
Requested: 3, in use: 64
perf: prctl(PR_FUTEX_HASH)
Also fix "Wokeup" in the 'futex wake' output, which should be "Woke up".
Fixes: 60035a3981a7 ("tools/perf: Allow to select the number of hash buckets")
Assisted-by: LLM
Signed-off-by: Michal Pluta <michalpl2003@gmail.com>
---
tools/perf/bench/futex-wake.c | 4 ++--
tools/perf/bench/futex.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 7674622639ca..2cbf31e121d5 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -89,7 +89,7 @@ static void print_summary(void)
double waketime_stddev = stddev_stats(&waketime_stats);
unsigned int wakeup_avg = avg_stats(&wakeup_stats);
- printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n",
+ printf("Woke up %d of %d threads in %.4f ms (+-%.2f%%)\n",
wakeup_avg,
params.nthreads,
waketime_avg / USEC_PER_MSEC,
@@ -223,7 +223,7 @@ int bench_futex_wake(int argc, const char **argv)
update_stats(&waketime_stats, runtime_us);
if (!params.silent) {
- printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
+ printf("[Run %d]: Woke up %d of %d threads in %.4f ms\n",
j + 1, nwoken, params.nthreads,
runtime_us / (double)USEC_PER_MSEC);
}
diff --git a/tools/perf/bench/futex.c b/tools/perf/bench/futex.c
index 5757d47f8f7c..be0cbc03682c 100644
--- a/tools/perf/bench/futex.c
+++ b/tools/perf/bench/futex.c
@@ -43,9 +43,9 @@ void futex_print_nbuckets(struct bench_futex_parameters *params)
printf("Can't query number of buckets: %m\n");
err(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
}
- printf("Requested number of hash buckets does not currently used.\n");
- printf("Requested: %d in usage: %d\n", params->nbuckets, ret);
- err(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
+ printf("Requested number of buckets differs from the number in use.\n");
+ printf("Requested: %d, in use: %d\n", params->nbuckets, ret);
+ errx(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
}
if (params->nbuckets == 0)
ret = asprintf(&futex_hash_mode, "Futex hashing: global hash");
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread