mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
perf test: Add a workload that forces context switches
This workload launches two processes that block when reading and writing to each other forcing the other process to be scheduled for each read/write pair. Signed-off-by: James Clark <james.clark@linaro.org> Cc: Amir Ayupov <aaupov@meta.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Leo Yan <leo.yan@arm.com> Cc: Mike Leach <mike.leach@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paschalis Mpeis <Paschalis.Mpeis@arm.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
d281fb9dfd
commit
4cb5dd0379
|
|
@ -55,15 +55,16 @@ OPTIONS
|
|||
|
||||
-w::
|
||||
--workload=::
|
||||
Run a built-in workload, to list them use '--list-workloads', current ones include:
|
||||
noploop, thloop, leafloop, sqrtloop, brstack, datasym and landlock.
|
||||
Run a built-in workload, to list them use '--list-workloads', current
|
||||
ones include: noploop, thloop, leafloop, sqrtloop, brstack, datasym,
|
||||
context_switch_loop and landlock.
|
||||
|
||||
Used with the shell script regression tests.
|
||||
|
||||
Some accept an extra parameter:
|
||||
|
||||
seconds: leafloop, noploop, sqrtloop, thloop
|
||||
nrloops: brstack
|
||||
nrloops: brstack, context_switch_loop
|
||||
|
||||
The datasym and landlock workloads don't accept any.
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ static struct test_workload *workloads[] = {
|
|||
&workload__traploop,
|
||||
&workload__inlineloop,
|
||||
&workload__jitdump,
|
||||
&workload__context_switch_loop,
|
||||
|
||||
#ifdef HAVE_RUST_SUPPORT
|
||||
&workload__code_with_type,
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ DECLARE_WORKLOAD(landlock);
|
|||
DECLARE_WORKLOAD(traploop);
|
||||
DECLARE_WORKLOAD(inlineloop);
|
||||
DECLARE_WORKLOAD(jitdump);
|
||||
DECLARE_WORKLOAD(context_switch_loop);
|
||||
|
||||
#ifdef HAVE_RUST_SUPPORT
|
||||
DECLARE_WORKLOAD(code_with_type);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ perf-test-y += landlock.o
|
|||
perf-test-y += traploop.o
|
||||
perf-test-y += inlineloop.o
|
||||
perf-test-y += jitdump.o
|
||||
perf-test-y += context_switch_loop.o
|
||||
|
||||
ifeq ($(CONFIG_RUST_SUPPORT),y)
|
||||
perf-test-y += code_with_type.o
|
||||
|
|
|
|||
110
tools/perf/tests/workloads/context_switch_loop.c
Normal file
110
tools/perf/tests/workloads/context_switch_loop.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../tests.h"
|
||||
|
||||
static int loops = 100;
|
||||
static char buf;
|
||||
int context_switch_loop_work = 1234;
|
||||
|
||||
#define write_block(fd) \
|
||||
do { \
|
||||
if (write(fd, &buf, 1) <= 0) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define read_block(fd) \
|
||||
do { \
|
||||
if (read(fd, &buf, 1) <= 0) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
/* Not static to avoid LTO clobbering the function name */
|
||||
int context_switch_loop_proc1(int in_fd, int out_fd);
|
||||
int context_switch_loop_proc1(int in_fd, int out_fd)
|
||||
{
|
||||
for (int i = 0; i < loops; i++) {
|
||||
read_block(in_fd);
|
||||
context_switch_loop_work += i * 3;
|
||||
write_block(out_fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int context_switch_loop_proc2(int in_fd, int out_fd);
|
||||
int context_switch_loop_proc2(int in_fd, int out_fd)
|
||||
{
|
||||
for (int i = 0; i < loops; i++) {
|
||||
write_block(out_fd);
|
||||
context_switch_loop_work += i * 7;
|
||||
read_block(in_fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Launches two processes that take turns to execute a multiplication N times
|
||||
*/
|
||||
static int context_switch_loop(int argc, const char **argv)
|
||||
{
|
||||
int a_to_b[2], b_to_a[2];
|
||||
pid_t proc1_pid;
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
if (argc > 0) {
|
||||
loops = atoi(argv[0]);
|
||||
if (loops < 0) {
|
||||
fprintf(stderr, "Invalid number of loops: %s\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe(a_to_b) || pipe(b_to_a)) {
|
||||
perror("Pipe error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
proc1_pid = fork();
|
||||
if (proc1_pid < 0) {
|
||||
perror("Fork error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!proc1_pid) {
|
||||
close(a_to_b[0]);
|
||||
close(b_to_a[1]);
|
||||
prctl(PR_SET_NAME, "proc1", 0, 0, 0);
|
||||
ret = context_switch_loop_proc1(b_to_a[0], a_to_b[1]);
|
||||
close(a_to_b[1]);
|
||||
close(b_to_a[0]);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
close(a_to_b[1]);
|
||||
close(b_to_a[0]);
|
||||
prctl(PR_SET_NAME, "proc2", 0, 0, 0);
|
||||
ret = context_switch_loop_proc2(a_to_b[0], b_to_a[1]);
|
||||
close(a_to_b[0]);
|
||||
close(b_to_a[1]);
|
||||
|
||||
if (ret) {
|
||||
kill(proc1_pid, SIGKILL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (waitpid(proc1_pid, &status, 0) != proc1_pid || !WIFEXITED(status) ||
|
||||
WEXITSTATUS(status))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_WORKLOAD(context_switch_loop);
|
||||
Loading…
Reference in New Issue
Block a user