~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/powerpc/benchmarks/fork.c

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0+
  2 
  3 /*
  4  * Context switch microbenchmark.
  5  *
  6  * Copyright 2018, Anton Blanchard, IBM Corp.
  7  */
  8 
  9 #define _GNU_SOURCE
 10 #include <assert.h>
 11 #include <errno.h>
 12 #include <getopt.h>
 13 #include <limits.h>
 14 #include <linux/futex.h>
 15 #include <pthread.h>
 16 #include <sched.h>
 17 #include <signal.h>
 18 #include <stdio.h>
 19 #include <stdlib.h>
 20 #include <string.h>
 21 #include <sys/shm.h>
 22 #include <sys/syscall.h>
 23 #include <sys/time.h>
 24 #include <sys/types.h>
 25 #include <sys/wait.h>
 26 #include <unistd.h>
 27 
 28 static unsigned int timeout = 30;
 29 
 30 static void set_cpu(int cpu)
 31 {
 32         cpu_set_t cpuset;
 33 
 34         if (cpu == -1)
 35                 return;
 36 
 37         CPU_ZERO(&cpuset);
 38         CPU_SET(cpu, &cpuset);
 39 
 40         if (sched_setaffinity(0, sizeof(cpuset), &cpuset)) {
 41                 perror("sched_setaffinity");
 42                 exit(1);
 43         }
 44 }
 45 
 46 static void start_process_on(void *(*fn)(void *), void *arg, int cpu)
 47 {
 48         int pid;
 49 
 50         pid = fork();
 51         if (pid == -1) {
 52                 perror("fork");
 53                 exit(1);
 54         }
 55 
 56         if (pid)
 57                 return;
 58 
 59         set_cpu(cpu);
 60 
 61         fn(arg);
 62 
 63         exit(0);
 64 }
 65 
 66 static 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;
 74 
 75 static void run_exec(void)
 76 {
 77         char *const argv[] = { "./exec_target", NULL };
 78 
 79         if (execve("./exec_target", argv, NULL) == -1) {
 80                 perror("execve");
 81                 exit(1);
 82         }
 83 }
 84 
 85 static void bench_fork(void)
 86 {
 87         while (1) {
 88                 pid_t pid = fork();
 89                 if (pid == -1) {
 90                         perror("fork");
 91                         exit(1);
 92                 }
 93                 if (pid == 0) {
 94                         if (do_exec)
 95                                 run_exec();
 96                         _exit(0);
 97                 }
 98                 pid = waitpid(pid, NULL, 0);
 99                 if (pid == -1) {
100                         perror("waitpid");
101                         exit(1);
102                 }
103                 iterations++;
104         }
105 }
106 
107 static void bench_vfork(void)
108 {
109         while (1) {
110                 pid_t pid = vfork();
111                 if (pid == -1) {
112                         perror("fork");
113                         exit(1);
114                 }
115                 if (pid == 0) {
116                         if (do_exec)
117                                 run_exec();
118                         _exit(0);
119                 }
120                 pid = waitpid(pid, NULL, 0);
121                 if (pid == -1) {
122                         perror("waitpid");
123                         exit(1);
124                 }
125                 iterations++;
126         }
127 }
128 
129 static void *null_fn(void *arg)
130 {
131         pthread_exit(NULL);
132 }
133 
134 static void bench_thread(void)
135 {
136         pthread_t tid;
137         cpu_set_t cpuset;
138         pthread_attr_t attr;
139         int rc;
140 
141         rc = pthread_attr_init(&attr);
142         if (rc) {
143                 errno = rc;
144                 perror("pthread_attr_init");
145                 exit(1);
146         }
147 
148         if (cpu != -1) {
149                 CPU_ZERO(&cpuset);
150                 CPU_SET(cpu, &cpuset);
151 
152                 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
153                 if (rc) {
154                         errno = rc;
155                         perror("pthread_attr_setaffinity_np");
156                         exit(1);
157                 }
158         }
159 
160         while (1) {
161                 rc = pthread_create(&tid, &attr, null_fn, NULL);
162                 if (rc) {
163                         errno = rc;
164                         perror("pthread_create");
165                         exit(1);
166                 }
167                 rc = pthread_join(tid, NULL);
168                 if (rc) {
169                         errno = rc;
170                         perror("pthread_join");
171                         exit(1);
172                 }
173                 iterations++;
174         }
175 }
176 
177 static void sigalrm_handler(int junk)
178 {
179         unsigned long i = iterations;
180 
181         printf("%ld\n", i - iterations_prev);
182         iterations_prev = i;
183 
184         if (--timeout == 0)
185                 kill(0, SIGUSR1);
186 
187         alarm(1);
188 }
189 
190 static void sigusr1_handler(int junk)
191 {
192         exit(0);
193 }
194 
195 static void *bench_proc(void *arg)
196 {
197         signal(SIGALRM, sigalrm_handler);
198         alarm(1);
199 
200         if (do_fork)
201                 bench_fork();
202         else if (do_vfork)
203                 bench_vfork();
204         else
205                 bench_thread();
206 
207         return NULL;
208 }
209 
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 },
216         { NULL },
217 };
218 
219 static void usage(void)
220 {
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");
227 }
228 
229 int main(int argc, char *argv[])
230 {
231         signed char c;
232 
233         while (1) {
234                 int option_index = 0;
235 
236                 c = getopt_long(argc, argv, "", options, &option_index);
237 
238                 if (c == -1)
239                         break;
240 
241                 switch (c) {
242                 case 0:
243                         if (options[option_index].flag != 0)
244                                 break;
245 
246                         usage();
247                         exit(1);
248                         break;
249 
250                 case 's':
251                         timeout = atoi(optarg);
252                         break;
253 
254                 default:
255                         usage();
256                         exit(1);
257                 }
258         }
259 
260         if (do_fork && do_vfork) {
261                 usage();
262                 exit(1);
263         }
264         if (do_exec && !do_fork && !do_vfork) {
265                 usage();
266                 exit(1);
267         }
268 
269         if (do_exec) {
270                 char *dirname = strdup(argv[0]);
271                 int i;
272                 i = strlen(dirname) - 1;
273                 while (i) {
274                         if (dirname[i] == '/') {
275                                 dirname[i] = '\0';
276                                 if (chdir(dirname) == -1) {
277                                         perror("chdir");
278                                         exit(1);
279                                 }
280                                 break;
281                         }
282                         i--;
283                 }
284         }
285 
286         if (exec_target) {
287                 exit(0);
288         }
289 
290         if (((argc - optind) != 1)) {
291                 cpu = -1;
292         } else {
293                 cpu = atoi(argv[optind++]);
294         }
295 
296         if (do_exec)
297                 exec_file = argv[0];
298 
299         set_cpu(cpu);
300 
301         printf("Using ");
302         if (do_fork)
303                 printf("fork");
304         else if (do_vfork)
305                 printf("vfork");
306         else
307                 printf("clone");
308 
309         if (do_exec)
310                 printf(" + exec");
311 
312         printf(" on cpu %d\n", cpu);
313 
314         /* Create a new process group so we can signal everyone for exit */
315         setpgid(getpid(), getpid());
316 
317         signal(SIGUSR1, sigusr1_handler);
318 
319         start_process_on(bench_proc, NULL, cpu);
320 
321         while (1)
322                 sleep(3600);
323 
324         return 0;
325 }
326 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp