1 /*
2 * lat_proc.c - process creation tests
3 *
4 * Usage: lat_proc [-P <parallelism] [-W <warmup>] [-N <repetitions>] procedure|fork|exec|shell
5 *
6 * TODO - linux clone, plan9 rfork, IRIX sproc().
7 *
8 * Copyright (c) 1994 Larry McVoy. Distributed under the FSF GPL with
9 * additional restriction that results may published only if
10 * (1) the benchmark is unmodified, and
11 * (2) the version in the sccsid below is included in the report.
12 * Support for this development by Sun Microsystems is gratefully acknowledged.
13 */
14 char *id = "$Id$\n";
15
16 #include "bench.h"
17
18
19 #ifdef STATIC
20 #define PROG "/tmp/hello-s"
21 #define STATIC_PREFIX "Static "
22 #else
23 #define PROG "/tmp/hello"
24 #define STATIC_PREFIX ""
25 #endif
26
27 void do_shell(iter_t iterations, void* cookie);
28 void do_forkexec(iter_t iterations,void* cookie);
29 void do_fork(iter_t iterations, void* cookie);
30 void do_procedure(iter_t iterations, void* cookie);
31
32 pid_t child_pid;
33
34
35 void
cleanup(iter_t iterations,void * cookie)36 cleanup(iter_t iterations, void* cookie)
37 {
38 if (iterations) return;
39
40 if (child_pid) {
41 kill(child_pid, SIGKILL);
42 waitpid(child_pid, NULL, 0);
43 child_pid = 0;
44 }
45 }
46
47 int
main(int ac,char ** av)48 main(int ac, char **av)
49 {
50 int parallel = 1;
51 int warmup = 0;
52 int repetitions = -1;
53 int c;
54 char* usage = "[-P <parallelism>] [-W <warmup>] [-N <repetitions>] procedure|fork|exec|shell\n";
55
56 while (( c = getopt(ac, av, "P:W:N:")) != EOF) {
57 switch(c) {
58 case 'P':
59 parallel = atoi(optarg);
60 if (parallel <= 0) lmbench_usage(ac, av, usage);
61 break;
62 case 'W':
63 warmup = atoi(optarg);
64 break;
65 case 'N':
66 repetitions = atoi(optarg);
67 break;
68 default:
69 lmbench_usage(ac, av, usage);
70 break;
71 }
72 }
73
74 if (optind + 1 != ac) { /* should have one argument left */
75 lmbench_usage(ac, av, usage);
76 }
77
78 if (!strcmp("procedure", av[optind])) {
79 benchmp(NULL, do_procedure, cleanup, 0, parallel,
80 warmup, repetitions, &ac);
81 micro("Procedure call", get_n());
82 } else if (!strcmp("fork", av[optind])) {
83 benchmp(NULL, do_fork, cleanup, 0, parallel,
84 warmup, repetitions, NULL);
85 micro(STATIC_PREFIX "Process fork+exit", get_n());
86 } else if (!strcmp("exec", av[optind])) {
87 benchmp(NULL, do_forkexec, cleanup, 0, parallel,
88 warmup, repetitions, NULL);
89 micro(STATIC_PREFIX "Process fork+execve", get_n());
90 } else if (!strcmp("shell", av[optind])) {
91 benchmp(NULL, do_shell, cleanup, 0, parallel,
92 warmup, repetitions, NULL);
93 micro(STATIC_PREFIX "Process fork+/bin/sh -c", get_n());
94 } else {
95 lmbench_usage(ac, av, usage);
96 }
97 return(0);
98 }
99
100 void
do_shell(iter_t iterations,void * cookie)101 do_shell(iter_t iterations, void* cookie)
102 {
103 signal(SIGCHLD, SIG_DFL);
104 handle_scheduler(benchmp_childid(), 0, 1);
105 while (iterations-- > 0) {
106 switch (child_pid = fork()) {
107 case -1:
108 perror("fork");
109 exit(1);
110
111 case 0: /* child */
112 handle_scheduler(benchmp_childid(), 1, 1);
113 close(1);
114 execlp("/bin/sh", "sh", "-c", PROG, 0);
115 exit(1);
116
117 default:
118 waitpid(child_pid, NULL,0);
119 }
120 child_pid = 0;
121 }
122 }
123
124 void
do_forkexec(iter_t iterations,void * cookie)125 do_forkexec(iter_t iterations, void* cookie)
126 {
127 char *nav[2];
128
129 signal(SIGCHLD, SIG_DFL);
130 handle_scheduler(benchmp_childid(), 0, 1);
131 while (iterations-- > 0) {
132 nav[0] = PROG;
133 nav[1] = 0;
134 switch (child_pid = fork()) {
135 case -1:
136 perror("fork");
137 exit(1);
138
139 case 0: /* child */
140 handle_scheduler(benchmp_childid(), 1, 1);
141 close(1);
142 execve(PROG, nav, 0);
143 exit(1);
144
145 default:
146 waitpid(child_pid, NULL,0);
147 }
148 child_pid = 0;
149 }
150 }
151
152 void
do_fork(iter_t iterations,void * cookie)153 do_fork(iter_t iterations, void* cookie)
154 {
155 signal(SIGCHLD, SIG_DFL);
156 handle_scheduler(benchmp_childid(), 0, 1);
157 while (iterations-- > 0) {
158 switch (child_pid = fork()) {
159 case -1:
160 perror("fork");
161 exit(1);
162
163 case 0: /* child */
164 handle_scheduler(benchmp_childid(), 1, 1);
165 exit(1);
166
167 default:
168 waitpid(child_pid, NULL,0);
169 }
170 child_pid = 0;
171 }
172 }
173
174 void
do_procedure(iter_t iterations,void * cookie)175 do_procedure(iter_t iterations, void* cookie)
176 {
177 int r = *(int *) cookie;
178 handle_scheduler(benchmp_childid(), 0, 1);
179 while (iterations-- > 0) {
180 use_int(r);
181 }
182 }
183