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