projects/linux·blob master · refs

110 lines · 2.1 KiB

1
2// SPDX-License-Identifier: GPL-2.0
3
4#include <linux/compiler.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <sys/prctl.h>
8#include <sys/wait.h>
9#include <unistd.h>
10
11#include "../tests.h"
12
13static int loops = 100;
14static char buf;
15int context_switch_loop_work = 1234;
16
17#define write_block(fd) \
18 do { \
19 if (write(fd, &buf, 1) <= 0) \
20 return 1; \
21 } while (0)
22
23#define read_block(fd) \
24 do { \
25 if (read(fd, &buf, 1) <= 0) \
26 return 1; \
27 } while (0)
28
29/* Not static to avoid LTO clobbering the function name */
30int context_switch_loop_proc1(int in_fd, int out_fd);
31int context_switch_loop_proc1(int in_fd, int out_fd)
32{
33 for (int i = 0; i < loops; i++) {
34 read_block(in_fd);
35 context_switch_loop_work += i * 3;
36 write_block(out_fd);
37 }
38 return 0;
39}
40
41int context_switch_loop_proc2(int in_fd, int out_fd);
42int context_switch_loop_proc2(int in_fd, int out_fd)
43{
44 for (int i = 0; i < loops; i++) {
45 write_block(out_fd);
46 context_switch_loop_work += i * 7;
47 read_block(in_fd);
48 }
49 return 0;
50}
51
52/*
53 * Launches two processes that take turns to execute a multiplication N times
54 */
55static int context_switch_loop(int argc, const char **argv)
56{
57 int a_to_b[2], b_to_a[2];
58 pid_t proc1_pid;
59 int status;
60 int ret;
61
62 if (argc > 0) {
63 loops = atoi(argv[0]);
64 if (loops < 0) {
65 fprintf(stderr, "Invalid number of loops: %s\n", argv[0]);
66 return 1;
67 }
68 }
69
70 if (pipe(a_to_b) || pipe(b_to_a)) {
71 perror("Pipe error");
72 return 1;
73 }
74
75 proc1_pid = fork();
76 if (proc1_pid < 0) {
77 perror("Fork error");
78 return 1;
79 }
80
81 if (!proc1_pid) {
82 close(a_to_b[0]);
83 close(b_to_a[1]);
84 prctl(PR_SET_NAME, "proc1", 0, 0, 0);
85 ret = context_switch_loop_proc1(b_to_a[0], a_to_b[1]);
86 close(a_to_b[1]);
87 close(b_to_a[0]);
88 exit(ret);
89 }
90
91 close(a_to_b[1]);
92 close(b_to_a[0]);
93 prctl(PR_SET_NAME, "proc2", 0, 0, 0);
94 ret = context_switch_loop_proc2(a_to_b[0], b_to_a[1]);
95 close(a_to_b[0]);
96 close(b_to_a[1]);
97
98 if (ret) {
99 kill(proc1_pid, SIGKILL);
100 return ret;
101 }
102
103 if (waitpid(proc1_pid, &status, 0) != proc1_pid || !WIFEXITED(status) ||
104 WEXITSTATUS(status))
105 return 1;
106
107 return 0;
108}
109
110DEFINE_WORKLOAD(context_switch_loop);