15 #define BAD_VERBOSE (-999999999)
17 #define difftime(a, b) \
18 ((double)(a)->tv_sec - (b)->tv_sec + \
19 ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
21 static char *cmdname(char *func)
26 sprintf(buf, "%s-%d", func, thread);
33 static int be_verbose(int verbose, struct timeval *next_time,
34 unsigned long num, unsigned long *next_num, int num_total)
41 if (next_time != NULL)
42 gettimeofday(&now, NULL);
44 /* A positive verbosity means to print every X iterations */
46 (next_num == NULL || num >= *next_num || num >= num_total)) {
49 next_time->tv_sec = now.tv_sec - verbose;
50 next_time->tv_usec = now.tv_usec;
55 /* A negative verbosity means to print at most each X seconds */
56 if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
57 next_time->tv_sec = now.tv_sec - verbose;
58 next_time->tv_usec = now.tv_usec;
67 static int get_verbose(char *func, const char *arg)
72 if (!arg || arg[0] == 'v')
74 else if (arg[0] == 's' || arg[0] == 'q')
77 verbose = (int)strtoul(arg, &end, 0);
79 fprintf(stderr, "%s: error: bad verbose option '%s'\n",
86 printf("Print status every %d seconds\n", -verbose);
87 else if (verbose == 1)
88 printf("Print status every operation\n");
90 printf("Print status every %d operations\n", verbose);
95 int main(int argc, char *argv[])
99 unsigned long count, i;
104 if (argc < 3 || argc > 5) {
106 "usage: %s <filename> <count> [verbose [threads]]\n",
111 count = strtoul(argv[2], &end, 0);
113 fprintf(stderr, "%s: error: bad iteration count '%s'\n",
118 verbose = get_verbose(argv[0], argv[3]);
119 if (verbose == BAD_VERBOSE)
123 threads = strtoul(argv[4], &end, 0);
125 fprintf(stderr, "%s: error: bad thread count '%s'\n",
131 for (i = 1; i <= threads; i++) {
134 fprintf(stderr, "%s: error: #%ld - %s\n",
135 cmdname(argv[0]), i, strerror(rc = errno));
137 } else if (rc == 0) {
141 printf("%s: thread #%ld (PID %d) started\n",
142 cmdname(argv[0]), i, rc);
146 if (threads && thread == 0) { /* parent process */
147 int live_threads = threads;
149 while (live_threads > 0) {
153 ret = waitpid(0, &status, 0);
159 fprintf(stderr, "%s: error: wait - %s\n",
160 argv[0], strerror(errno));
165 * This is a hack. We _should_ be able to use
166 * WIFEXITED(status) to see if there was an
167 * error, but it appears to be broken and it
168 * always returns 1 (OK). See wait(2).
170 int err = WEXITSTATUS(status);
171 if (err || WIFSIGNALED(status))
173 "%s: error: PID %d had rc=%d\n",
182 struct timeval start, end, next_time;
183 unsigned long next_count;
186 gettimeofday(&start, NULL);
187 next_time.tv_sec = start.tv_sec - verbose;
188 next_time.tv_usec = start.tv_usec;
190 for (i = 0, next_count = verbose; i < count; i++) {
192 sprintf(filename, "%s-%d-%ld",
195 sprintf(filename, "%s-%ld", argv[1], i);
197 rc = mknod(filename, S_IFREG, 0);
199 fprintf(stderr, "%s: error: mknod(%s): %s\n",
200 cmdname(argv[0]), filename,
205 if (unlink(filename) < 0) {
206 fprintf(stderr, "%s: error: unlink(%s): %s\n",
207 cmdname(argv[0]), filename,
212 if (be_verbose(verbose, &next_time,i,&next_count,count))
213 printf("%s: number %ld\n", cmdname(argv[0]), i);
216 gettimeofday(&end, NULL);
217 diff = difftime(&end, &start);
219 printf("%s: %ldx2 files in %.4gs (%.4g ops/s): rc = %d: %s",
220 cmdname(argv[0]), i, diff, (double)i * 2 / diff,
221 rc, ctime(&end.tv_sec));