kernel: scheduling fix for ARM
[minix.git] / benchmarks / unixbench-5.1.2 / src / fstime.c
blob1ed40771249ca7f8c2dcb8fd75577744078e2081
1 /*******************************************************************************
2 * The BYTE UNIX Benchmarks - Release 3
3 * Module: fstime.c SID: 3.5 5/15/91 19:30:19
5 *******************************************************************************
6 * Bug reports, patches, comments, suggestions should be sent to:
8 * Ben Smith, Rick Grehan or Tom Yager
9 * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
11 *******************************************************************************
12 * Modification Log:
13 * $Header: fstime.c,v 3.4 87/06/22 14:23:05 kjmcdonell Beta $
14 * 10/19/89 - rewrote timing calcs and added clock check (Ben Smith)
15 * 10/26/90 - simplify timing, change defaults (Tom Yager)
16 * 11/16/90 - added better error handling and changed output format (Ben Smith)
17 * 11/17/90 - changed the whole thing around (Ben Smith)
18 * 2/22/91 - change a few style elements and improved error handling (Ben Smith)
19 * 4/17/91 - incorporated suggestions from Seckin Unlu (seckin@sumac.intel.com)
20 * 4/17/91 - limited size of file, will rewind when reaches end of file
21 * 7/95 - fixed mishandling of read() and write() return codes
22 * Carl Emilio Prelz <fluido@telepac.pt>
23 * 12/95 - Massive changes. Made sleep time proportional increase with run
24 * time; added fsbuffer and fsdisk variants; added partial counting
25 * of partial reads/writes (was *full* credit); added dual syncs.
26 * David C Niemi <niemi@tux.org>
27 * 10/22/97 - code cleanup to remove ANSI C compiler warnings
28 * Andy Kahn <kahn@zk3.dec.com>
29 * 9/24/07 - Separate out the read and write tests;
30 * output the actual time used in the results.
31 * Ian Smith <johantheghost at yahoo period com>
32 ******************************************************************************/
33 char SCCSid[] = "@(#) @(#)fstime.c:3.5 -- 5/15/91 19:30:19";
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <sys/time.h>
43 #define SECONDS 10
45 #define MAX_BUFSIZE 8192
47 /* This must be set to the smallest BUFSIZE or 1024, whichever is smaller */
48 #define COUNTSIZE 256
49 #define HALFCOUNT (COUNTSIZE/2) /* Half of COUNTSIZE */
51 #define FNAME0 "dummy0"
52 #define FNAME1 "dummy1"
54 #ifndef MINIX
55 extern void sync(void);
56 #else
57 extern int sync(void);
58 #endif
60 int w_test(int timeSecs);
61 int r_test(int timeSecs);
62 int c_test(int timeSecs);
64 long read_score = 1, write_score = 1, copy_score = 1;
66 /****************** GLOBALS ***************************/
68 /* The buffer size for the tests. */
69 int bufsize = 1024;
72 * The max number of 1024-byte blocks in the file.
73 * Don't limit it much, so that memory buffering
74 * can be overcome.
76 int max_blocks = 2000;
78 /* The max number of BUFSIZE blocks in the file. */
79 int max_buffs = 2000;
81 /* Countable units per 1024 bytes */
82 int count_per_k;
84 /* Countable units per bufsize */
85 int count_per_buf;
87 /* The actual buffer. */
88 /* char *buf = 0; */
89 /* Let's carry on using a static buffer for this, like older versions
90 * of the code did. It turns out that if you use a malloc buffer,
91 * it goes 50% slower on reads, when using a 4k buffer -- at least on
92 * my OpenSUSE 10.2 system.
93 * What up wit dat?
95 char buf[MAX_BUFSIZE];
97 int f;
98 int g;
99 int i;
100 void stop_count(int);
101 void clean_up(int);
102 int sigalarm = 0;
104 /******************** MAIN ****************************/
106 int main(int argc, char *argv[])
108 /* The number of seconds to run for. */
109 int seconds = SECONDS;
111 /* The type of test to run. */
112 char test = 'c';
114 int status;
115 int i;
117 for (i = 1; i < argc; ++i) {
118 if (argv[i][0] == '-') {
119 switch (argv[i][1]) {
120 case 'c':
121 case 'r':
122 case 'w':
123 test = argv[i][1];
124 break;
125 case 'b':
126 bufsize = atoi(argv[++i]);
127 break;
128 case 'm':
129 max_blocks = atoi(argv[++i]);
130 break;
131 case 't':
132 seconds = atoi(argv[++i]);
133 break;
134 case 'd':
135 if (chdir(argv[++i]) < 0) {
136 perror("fstime: chdir");
137 exit(1);
139 break;
140 default:
141 fprintf(stderr, "Usage: fstime [-c|-r|-w] [-b <bufsize>] [-m <max_blocks>] [-t <seconds>]\n");
142 exit(2);
144 } else {
145 fprintf(stderr, "Usage: fstime [-c|-r|-w] [-b <bufsize>] [-m <max_blocks>] [-t <seconds>]\n");
146 exit(2);
150 if (bufsize < COUNTSIZE || bufsize > MAX_BUFSIZE) {
151 fprintf(stderr, "fstime: buffer size must be in range %d-%d\n",
152 COUNTSIZE, 1024*1024);
153 exit(3);
155 if (max_blocks < 1 || max_blocks > 1024*1024) {
156 fprintf(stderr, "fstime: max blocks must be in range %d-%d\n",
157 1, 1024*1024);
158 exit(3);
160 if (seconds < 1 || seconds > 3600) {
161 fprintf(stderr, "fstime: time must be in range %d-%d seconds\n",
162 1, 3600);
163 exit(3);
166 max_buffs = max_blocks * 1024 / bufsize;
167 count_per_k = 1024 / COUNTSIZE;
168 count_per_buf = bufsize / COUNTSIZE;
171 if ((buf = malloc(bufsize)) == 0) {
172 fprintf(stderr, "fstime: failed to malloc %d bytes\n", bufsize);
173 exit(4);
177 if((f = creat(FNAME0, 0600)) == -1) {
178 perror("fstime: creat");
179 exit(1);
181 close(f);
183 if((g = creat(FNAME1, 0600)) == -1) {
184 perror("fstime: creat");
185 exit(1);
187 close(g);
189 if( (f = open(FNAME0, 2)) == -1) {
190 perror("fstime: open");
191 exit(1);
193 if( ( g = open(FNAME1, 2)) == -1 ) {
194 perror("fstime: open");
195 exit(1);
198 /* fill buffer */
199 for (i=0; i < bufsize; ++i)
200 buf[i] = i & 0xff;
202 signal(SIGKILL,clean_up);
205 * Run the selected test.
206 * When I got here, this program ran full 30-second tests for
207 * write, read, and copy, outputting the results for each. BUT
208 * only the copy results are actually used in the benchmark index.
209 * With multiple iterations and three sets of FS tests, that amounted
210 * to about 10 minutes of wasted time per run.
212 * So, I've made the test selectable. Except that the read and write
213 * passes are used to create the test file and calibrate the rates used
214 * to tweak the results of the copy test. So, for copy tests, we do
215 * a few seconds of write and read to prime the pump.
217 * Note that this will also pull the file into the FS cache on any
218 * modern system prior to the copy test. Whether this is good or
219 * bad is a matter of perspective, but it's how it was when I got
220 * here.
222 * Ian Smith <johantheghost at yahoo period com> 21 Sep 2007
224 switch (test) {
225 case 'w':
226 status = w_test(seconds);
227 break;
228 case 'r':
229 w_test(2);
230 status = r_test(seconds);
231 break;
232 case 'c':
233 w_test(2);
234 r_test(2);
235 status = c_test(seconds);
236 break;
237 default:
238 fprintf(stderr, "fstime: unknown test \'%c\'\n", test);
239 exit(6);
241 if (status) {
242 clean_up(0);
243 exit(1);
246 clean_up(0);
247 exit(0);
251 static double getFloatTime(void)
253 struct timeval t;
255 gettimeofday(&t, 0);
256 return (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
261 * Run the write test for the time given in seconds.
263 int w_test(int timeSecs)
265 unsigned long counted = 0L;
266 unsigned long tmp;
267 long f_blocks;
268 double start, end;
269 extern int sigalarm;
271 /* Sync and let it settle */
272 sync();
273 sleep(2);
274 sync();
275 sleep(2);
277 /* Set an alarm. */
278 sigalarm = 0;
279 signal(SIGALRM, stop_count);
280 alarm(timeSecs);
282 start = getFloatTime();
284 while (!sigalarm) {
285 for(f_blocks=0; f_blocks < max_buffs; ++f_blocks) {
286 if ((tmp=write(f, buf, bufsize)) != bufsize) {
287 if (errno != EINTR) {
288 perror("fstime: write");
289 return(-1);
291 stop_count(0);
292 counted += ((tmp+HALFCOUNT)/COUNTSIZE);
293 } else
294 counted += count_per_buf;
296 lseek(f, 0L, 0); /* rewind */
299 /* stop clock */
300 end = getFloatTime();
301 write_score = (long) ((double) counted / ((end - start) * count_per_k));
302 printf("Write done: %ld in %.4f, score %ld\n",
303 counted, end - start, write_score);
306 * Output the test results. Use the true time.
308 fprintf(stderr, "COUNT|%ld|0|KBps\n", write_score);
309 fprintf(stderr, "TIME|%.1f\n", end - start);
311 return(0);
315 * Run the read test for the time given in seconds.
317 int r_test(int timeSecs)
319 unsigned long counted = 0L;
320 unsigned long tmp;
321 double start, end;
322 extern int sigalarm;
323 extern int errno;
325 /* Sync and let it settle */
326 sync();
327 sleep(2);
328 sync();
329 sleep(2);
331 /* rewind */
332 errno = 0;
333 lseek(f, 0L, 0);
335 /* Set an alarm. */
336 sigalarm = 0;
337 signal(SIGALRM, stop_count);
338 alarm(timeSecs);
340 start = getFloatTime();
342 while (!sigalarm) {
343 /* read while checking for an error */
344 if ((tmp=read(f, buf, bufsize)) != bufsize) {
345 switch(errno) {
346 case 0:
347 case EINVAL:
348 lseek(f, 0L, 0); /* rewind at end of file */
349 counted += (tmp+HALFCOUNT)/COUNTSIZE;
350 continue;
351 case EINTR:
352 stop_count(0);
353 counted += (tmp+HALFCOUNT)/COUNTSIZE;
354 break;
355 default:
356 perror("fstime: read");
357 return(-1);
358 break;
360 } else
361 counted += count_per_buf;
364 /* stop clock */
365 end = getFloatTime();
366 read_score = (long) ((double) counted / ((end - start) * count_per_k));
367 printf("Read done: %ld in %.4f, score %ld\n",
368 counted, end - start, read_score);
371 * Output the test results. Use the true time.
373 fprintf(stderr, "COUNT|%ld|0|KBps\n", read_score);
374 fprintf(stderr, "TIME|%.1f\n", end - start);
376 return(0);
381 * Run the copy test for the time given in seconds.
383 int c_test(int timeSecs)
385 unsigned long counted = 0L;
386 unsigned long tmp;
387 double start, end;
388 extern int sigalarm;
390 sync();
391 sleep(2);
392 sync();
393 sleep(1);
395 /* rewind */
396 errno = 0;
397 lseek(f, 0L, 0);
399 /* Set an alarm. */
400 sigalarm = 0;
401 signal(SIGALRM, stop_count);
402 alarm(timeSecs);
404 start = getFloatTime();
406 while (!sigalarm) {
407 if ((tmp=read(f, buf, bufsize)) != bufsize) {
408 switch(errno) {
409 case 0:
410 case EINVAL:
411 lseek(f, 0L, 0); /* rewind at end of file */
412 lseek(g, 0L, 0); /* rewind the output too */
413 continue;
414 case EINTR:
415 /* part credit for leftover bytes read */
416 counted += ( (tmp * write_score) /
417 (read_score + write_score)
418 + HALFCOUNT) / COUNTSIZE;
419 stop_count(0);
420 break;
421 default:
422 perror("fstime: copy read");
423 return(-1);
424 break;
426 } else {
427 if ((tmp=write(g, buf, bufsize)) != bufsize) {
428 if (errno != EINTR) {
429 perror("fstime: copy write");
430 return(-1);
432 counted += (
433 /* Full credit for part of buffer written */
434 tmp +
436 /* Plus part credit having read full buffer */
437 ( ((bufsize - tmp) * write_score) /
438 (read_score + write_score) )
439 + HALFCOUNT) / COUNTSIZE;
440 stop_count(0);
441 } else
442 counted += count_per_buf;
446 /* stop clock */
447 end = getFloatTime();
448 copy_score = (long) ((double) counted / ((end - start) * count_per_k));
449 printf("Copy done: %ld in %.4f, score %ld\n",
450 counted, end - start, copy_score);
453 * Output the test results. Use the true time.
455 fprintf(stderr, "COUNT|%ld|0|KBps\n", copy_score);
456 fprintf(stderr, "TIME|%.1f\n", end - start);
458 return(0);
461 void stop_count(int sig)
463 extern int sigalarm;
464 sigalarm = 1;
467 void clean_up(int sig)
469 unlink(FNAME0);
470 unlink(FNAME1);