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