Files
linux/tools/perf/tests/workloads/thloop.c
Ian Rogers 810d0c9117 perf tests workloads: Support sub-second durations in noploop and thloop
Currently, the noploop and thloop workloads only support sleep durations
in integer seconds because they parse the argument using atoi() and use
alarm() for timer signaling.

To support much shorter execution times in tests (speeding up test suites
and allowing faster retries), change the input parsing to use atof() for
double floating-point seconds. Use ualarm() for fractional durations less
than 1.0 seconds, and fall back to alarm() for durations of 1.0 second or
more.

Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-06-30 17:09:13 -07:00

89 lines
1.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <linux/compiler.h>
#include "../tests.h"
static volatile sig_atomic_t done;
/* We want to check this symbol in perf report */
noinline void test_loop(void);
static void sighandler(int sig __maybe_unused)
{
done = 1;
}
noinline void test_loop(void)
{
while (!done);
}
static void *thfunc(void *arg)
{
void (*loop_fn)(void) = arg;
loop_fn();
return NULL;
}
static int thloop(int argc, const char **argv)
{
int nt = 2, err = 1;
double sec = 1.0;
pthread_t *thread_list = NULL;
if (argc > 0)
sec = atof(argv[0]);
if (!(sec > 0.0)) {
fprintf(stderr, "Error: seconds (%f) must be > 0\n", sec);
return 1;
}
if (argc > 1)
nt = atoi(argv[1]);
if (nt <= 0) {
fprintf(stderr, "Error: thread count (%d) must be >= 1\n", nt);
return 1;
}
signal(SIGINT, sighandler);
signal(SIGALRM, sighandler);
thread_list = calloc(nt, sizeof(pthread_t));
if (thread_list == NULL) {
fprintf(stderr, "Error: malloc failed for %d threads\n", nt);
goto out;
}
for (int i = 1; i < nt; i++) {
int ret = pthread_create(&thread_list[i], NULL, thfunc, test_loop);
if (ret) {
fprintf(stderr, "Error: failed to create thread %d\n", i);
done = 1; // Ensure started threads terminate.
goto out;
}
}
if (sec < 1.0) {
useconds_t usecs = (useconds_t)(sec * 1000000.0);
ualarm(usecs > 0 ? usecs : 1, 0);
} else
alarm((unsigned int)sec);
test_loop();
err = 0;
out:
for (int i = 1; i < nt; i++) {
if (thread_list && thread_list[i])
pthread_join(thread_list[i], /*retval=*/NULL);
}
free(thread_list);
return err;
}
DEFINE_WORKLOAD(thloop);