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