1 // SPDX-License-Identifier: GPL-2.0+
4 * Context switch microbenchmark.
6 * Copyright 2018, Anton Blanchard, IBM Corp.
14 #include <linux/futex.h>
22 #include <sys/syscall.h>
24 #include <sys/types.h>
28 static unsigned int timeout = 30;
30 static void set_cpu(int cpu)
38 CPU_SET(cpu, &cpuset);
40 if (sched_setaffinity(0, sizeof(cpuset), &cpuset)) {
41 perror("sched_setaffinity");
46 static void start_process_on(void *(*fn)(void *), void *arg, int cpu)
67 static int do_fork = 0;
68 static int do_vfork = 0;
69 static int do_exec = 0;
70 static char *exec_file;
71 static int exec_target = 0;
72 static unsigned long iterations;
73 static unsigned long iterations_prev;
75 static void run_exec(void)
77 char *const argv[] = { "./exec_target", NULL };
79 if (execve("./exec_target", argv, NULL) == -1) {
85 static void bench_fork(void)
98 pid = waitpid(pid, NULL, 0);
107 static void bench_vfork(void)
120 pid = waitpid(pid, NULL, 0);
129 static void *null_fn(void *arg)
134 static void bench_thread(void)
141 rc = pthread_attr_init(&attr);
144 perror("pthread_attr_init");
150 CPU_SET(cpu, &cpuset);
152 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
155 perror("pthread_attr_setaffinity_np");
161 rc = pthread_create(&tid, &attr, null_fn, NULL);
164 perror("pthread_create");
167 rc = pthread_join(tid, NULL);
170 perror("pthread_join");
177 static void sigalrm_handler(int junk)
179 unsigned long i = iterations;
181 printf("%ld\n", i - iterations_prev);
190 static void sigusr1_handler(int junk)
195 static void *bench_proc(void *arg)
197 signal(SIGALRM, sigalrm_handler);
210 static struct option options[] = {
211 { "fork", no_argument, &do_fork, 1 },
212 { "vfork", no_argument, &do_vfork, 1 },
213 { "exec", no_argument, &do_exec, 1 },
214 { "timeout", required_argument, 0, 's' },
215 { "exec-target", no_argument, &exec_target, 1 },
219 static void usage(void)
221 fprintf(stderr, "Usage: fork <options> CPU\n\n");
222 fprintf(stderr, "\t\t--fork\tUse fork() (default threads)\n");
223 fprintf(stderr, "\t\t--vfork\tUse vfork() (default threads)\n");
224 fprintf(stderr, "\t\t--exec\tAlso exec() (default no exec)\n");
225 fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n");
226 fprintf(stderr, "\t\t--exec-target\tInternal option for exec workload\n");
229 int main(int argc, char *argv[])
234 int option_index = 0;
236 c = getopt_long(argc, argv, "", options, &option_index);
243 if (options[option_index].flag != 0)
251 timeout = atoi(optarg);
260 if (do_fork && do_vfork) {
264 if (do_exec && !do_fork && !do_vfork) {
270 char *dirname = strdup(argv[0]);
272 i = strlen(dirname) - 1;
274 if (dirname[i] == '/') {
276 if (chdir(dirname) == -1) {
290 if (((argc - optind) != 1)) {
293 cpu = atoi(argv[optind++]);
312 printf(" on cpu %d\n", cpu);
314 /* Create a new process group so we can signal everyone for exit */
315 setpgid(getpid(), getpid());
317 signal(SIGUSR1, sigusr1_handler);
319 start_process_on(bench_proc, NULL, cpu);