mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-23 20:18:21 -04:00
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>
111 lines
2.1 KiB
C
111 lines
2.1 KiB
C
|
|
// 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);
|