xref: /freebsd/tools/test/stress2/tools/bench.c (revision c03c5b1c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Dell EMC Isilon
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 #include <sys/param.h>
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <sys/wait.h>
33 
34 #include <machine/atomic.h>
35 
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <unistd.h>
44 
45 #define PARALLEL 3
46 #define SYNC 0
47 
48 static void cr1(void);
49 static void cr2(void);
50 static void cr3(void);
51 static void rn1(void);
52 static void rw1(void);
53 static void rw2(void);
54 static void (*functions[])(void) = {&cr1, &cr2, &cr3, &rn1, &rw1, &rw2};
55 
56 static volatile u_int *share;
57 static int tests;
58 
59 static void
60 cr1(void)
61 {
62 	int fd, i, j;
63 	int loops = 9000;
64 	char file[128];
65 
66 	setproctitle("%s sync", __func__);
67 	atomic_add_int(&share[SYNC], 1);
68 	while (share[SYNC] != (volatile u_int)tests * PARALLEL)
69 		usleep(100);
70 	setproctitle("%s", __func__);
71 	for (j = 0; j < 10; j++) {
72 		for (i = 0; i < loops; i++) {
73 			snprintf(file, sizeof(file), "%s.%06d.%03d",
74 			    __func__, getpid(), i);
75 			if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC,
76 			    DEFFILEMODE)) == -1)
77 				err(1, "open(%s)", file);
78 			close(fd);
79 			if (i % 1000 == 0)
80 				usleep(100);
81 		}
82 		for (i = 0; i < loops; i++) {
83 			snprintf(file, sizeof(file), "%s.%06d.%03d",
84 			    __func__, getpid(), i);
85 			if (unlink(file) == -1)
86 				err(1, "unlink(%s)", file);
87 		}
88 	}
89 }
90 
91 static void
92 cr2(void)
93 {
94 	int fd, i, j;
95 	char file[1024];
96 
97 	setproctitle("%s sync", __func__);
98 	atomic_add_int(&share[SYNC], 1);
99 	while (share[SYNC] != (volatile u_int)tests * PARALLEL)
100 		usleep(100);
101 	setproctitle("%s", __func__);
102 	for (j = 0; j < 3; j++) {
103 		for (i = 0; i < 40000; i++) {
104 			snprintf(file, sizeof(file), "%s.%06d.%03d",
105 			    __func__, getpid(), i);
106 			if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC,
107 			    DEFFILEMODE)) == -1)
108 				err(1, "open(%s)", file);
109 			close(fd);
110 			if (unlink(file) == -1)
111 				err(1, "unlink(%s)", file);
112 			if (i % 1000 == 0)
113 				usleep(100);
114 		}
115 	}
116 }
117 
118 static void
119 cr3(void)
120 {
121 	int fd, i, j;
122 	int loops = 10000;
123 	char file[1024], path[1024];
124 
125 	setproctitle("%s sync", __func__);
126 	atomic_add_int(&share[SYNC], 1);
127 	while (share[SYNC] != (volatile u_int)tests * PARALLEL)
128 		usleep(100);
129 	setproctitle("%s", __func__);
130 	getcwd(path, sizeof(path));
131 	for (j = 0; j < 7; j++) {
132 		for (i = 0; i < loops; i++) {
133 			snprintf(file, sizeof(file), "%s/%s.%06d.%03d",
134 			    path, __func__, getpid(), i);
135 			if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC,
136 			    DEFFILEMODE)) == -1)
137 				err(1, "open(%s)", file);
138 			close(fd);
139 			if (i % 1000 == 0)
140 				usleep(100);
141 		}
142 		for (i = 0; i < loops; i++) {
143 			snprintf(file, sizeof(file), "%s/%s.%06d.%03d",
144 			    path, __func__, getpid(), i);
145 			if (unlink(file) == -1)
146 				err(1, "unlink(%s)", file);
147 		}
148 	}
149 }
150 
151 static void
152 rn1(void)
153 {
154 	int fd, i, j;
155 	int loops = 10000;
156 	char file[128], new[128];
157 
158 	setproctitle("%s sync", __func__);
159 	atomic_add_int(&share[SYNC], 1);
160 	while (share[SYNC] != (volatile u_int)tests * PARALLEL)
161 		usleep(100);
162 	setproctitle("%s", __func__);
163 
164 	for (j = 0; j < 8; j++) {
165 		for (i = 0; i < loops; i++) {
166 			snprintf(file, sizeof(file), "%s.%06d.%03d",
167 			    __func__, getpid(), i);
168 			if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC,
169 			    DEFFILEMODE)) == -1)
170 				err(1, "open(%s)", file);
171 			close(fd);
172 			snprintf(new, sizeof(new), "%s.%06d.%03d.new",
173 			    __func__, getpid(), i);
174 			if (rename(file, new) == -1)
175 				err(1, "rename(%s, %s)", file, new);
176 			if (unlink(new) == -1)
177 				err(1, "unlink(%s)", new);
178 			if (i % 1000 == 0)
179 				usleep(100);
180 		}
181 	}
182 }
183 
184 static void
185 rw1(void)
186 {
187 	int fd, i;
188 	int loops = 10000;
189 	char buf[512], file[128];
190 
191 	setproctitle("%s sync", __func__);
192 	atomic_add_int(&share[SYNC], 1);
193 	while (share[SYNC] != (volatile u_int)tests * PARALLEL)
194 		usleep(100);
195 
196 	setproctitle("%s", __func__);
197         memset(buf, 0, sizeof(buf));
198         for (i = 0; i < loops; i++) {
199                 snprintf(file, sizeof(file), "rw1.%06d.%03d", getpid(), i);
200                 if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC,
201                     DEFFILEMODE)) == -1)
202                         err(1, "open(%s)", file);
203                 if (write(fd, buf, sizeof(buf)) != sizeof(buf))
204                         err(1, "write(%s)", file);
205                 close(fd);
206         }
207         for (i = 0; i < loops; i++) {
208                 snprintf(file, sizeof(file), "rw1.%06d.%03d", getpid(), i);
209                 if ((fd = open(file, O_RDONLY)) == -1)
210                         err(1, "open(%s)", file);
211                 if (read(fd, buf, sizeof(buf)) != sizeof(buf))
212                         err(1, "write(%s)", file);
213                 close(fd);
214                 usleep(100);
215         }
216         for (i = 0; i < loops; i++) {
217                 snprintf(file, sizeof(file), "rw1.%06d.%03d", getpid(), i);
218                 if (unlink(file) == -1)
219                         err(1, "unlink(%s)", file);
220         }
221 }
222 
223 static void
224 rw2(void)
225 {
226 	int fd, i;
227 	int loops = 8000;
228 	int siz = 4096;
229 	char *buf, file[128];
230 
231 	setproctitle("%s sync", __func__);
232 	atomic_add_int(&share[SYNC], 1);
233 	while (share[SYNC] != (volatile u_int)tests * PARALLEL)
234 		usleep(100);
235 
236 	setproctitle("%s", __func__);
237 	buf = calloc(1, siz);
238         for (i = 0; i < loops; i++) {
239                 snprintf(file, sizeof(file), "rw1.%06d.%03d", getpid(), i);
240                 if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC,
241                     DEFFILEMODE)) == -1)
242                         err(1, "open(%s)", file);
243                 if (write(fd, buf, siz) != siz)
244                         err(1, "write(%s)", file);
245                 close(fd);
246         }
247         for (i = 0; i < loops; i++) {
248                 snprintf(file, sizeof(file), "rw1.%06d.%03d", getpid(), i);
249                 if ((fd = open(file, O_RDONLY)) == -1)
250                         err(1, "open(%s)", file);
251                 if (read(fd, buf, siz) != siz)
252                         err(1, "write(%s)", file);
253                 close(fd);
254                 usleep(100);
255         }
256         for (i = 0; i < loops; i++) {
257                 snprintf(file, sizeof(file), "rw1.%06d.%03d", getpid(), i);
258                 if (unlink(file) == -1)
259                         err(1, "unlink(%s)", file);
260         }
261 }
262 
263 static void
264 spawn(void f(), int idx)
265 {
266 	pid_t pids[PARALLEL];
267 	int i, status;
268 	char dir[128];
269 
270 	snprintf(dir, sizeof(dir), "f%d.%d.d",getpid(), idx);
271 	rmdir(dir);
272 	if (mkdir(dir, 0770) == -1)
273 		err(1, "mkdir(%s)", dir);
274 	if (chdir(dir) == -1)
275 		err(1, "chdir(%s)", dir);
276 	for (i = 0; i < PARALLEL; i++) {
277 		if ((pids[i] = fork()) == 0) {
278 			f();
279 			_exit(0);
280 		}
281 		if (pids[i] == -1)
282 			err(1, "fork(). %s:%d", __func__, __LINE__);
283 	}
284 	for (i = 0; i < PARALLEL; i++) {
285 		if (waitpid(pids[i], &status, 0) != pids[i])
286 			err(1, "waitpid(). %s:%d", __func__, __LINE__);
287 	}
288 	if (chdir("..") == -1)
289 		err(1, "chdir(..)");
290 	if (rmdir(dir) == -1)
291 		err(1, "rmdir(%s)", dir);
292 
293 }
294 
295 void
296 usage(void)
297 {
298 	fprintf(stderr, "Usage: %s [-t]\n", getprogname());
299 	exit(1);
300 }
301 
302 int
303 main(int argc, char *argv[])
304 {
305 	pid_t *pids;
306 	struct timeval t1, t2, diff;
307 	size_t len;
308 	time_t start __unused;
309 	int ch, i, status, timing;
310 
311 	timing = 0;
312 	while ((ch = getopt(argc, argv, "t")) != -1)
313 		switch(ch) {
314 		case 't':
315 			timing = 1;
316 			break;
317 		default:
318 			usage();
319 		}
320 	argc -= optind;
321 	argv += optind;
322 
323 	setproctitle("%s", __func__);
324 	tests = (int)(sizeof(functions) / sizeof(functions[0]));
325 	pids = malloc(tests * sizeof(pid_t));
326 	len = PAGE_SIZE;
327 	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
328 	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
329 		err(1, "mmap");
330 
331 	gettimeofday(&t1, NULL);
332 	for (i = 0; i < tests; i++) {
333 		if ((pids[i] = fork()) == 0) {
334 			start = time(NULL);
335 			spawn(functions[i], i);
336 #if defined(DEBUG)
337 			fprintf(stderr, "%d: %ld elapsed\n", i ,
338 			    (long)(time(NULL) - start));
339 #endif
340 			_exit(0);
341 		}
342 		if (pids[i] == -1)
343 			err(1, "fork(). %s:%d", __func__, __LINE__);
344 	}
345 	for (i = 0; i < tests; i++) {
346 		if (waitpid(pids[i], &status, 0) != pids[i])
347 			err(1, "waitpid(%d). i=%d %s:%d", pids[i], i,
348 					__func__, __LINE__);
349 	}
350 	gettimeofday(&t2, NULL);
351 	timersub(&t2, &t1, &diff);
352 	if (timing == 1)
353 		printf("%jd.%06ld\n",(intmax_t)diff.tv_sec, diff.tv_usec);
354 
355 	return (0);
356 }
357