Commit | Line | Data |
---|---|---|
e29834b8 MW |
1 | #include <errno.h> |
2 | #include <stdarg.h> | |
3 | #include <stdio.h> | |
4 | #include <stdlib.h> | |
5 | #include <string.h> | |
6 | #include <time.h> | |
7 | ||
8 | #include <unistd.h> | |
9 | #include <sys/resource.h> | |
10 | #include <sys/time.h> | |
11 | #include <sys/wait.h> | |
12 | ||
13 | static const char *progname = "timeit"; | |
14 | ||
15 | static void set_progname(const char *prog) | |
16 | { | |
17 | const char *p; | |
18 | ||
19 | p = strrchr(prog, '/'); | |
20 | progname = p ? p + 1 : progname; | |
21 | } | |
22 | ||
23 | static void lose(const char *msg, ...) | |
24 | { | |
25 | va_list ap; | |
26 | ||
27 | va_start(ap, msg); | |
28 | fprintf(stderr, "%s: ", progname); | |
29 | vfprintf(stderr, msg, ap); | |
30 | fputc('\n', stderr); | |
31 | va_end(ap); | |
32 | exit(127); | |
33 | } | |
34 | ||
35 | static double timeval_to_float(const struct timeval *tv) | |
36 | { return (tv->tv_sec + tv->tv_usec*1e-6); } | |
37 | ||
38 | int main(int argc, char *argv[]) | |
39 | { | |
40 | struct rusage ru; | |
41 | struct timeval t0, t1, t; | |
42 | pid_t kid; | |
43 | int i, st; | |
44 | ||
45 | set_progname(argv[0]); | |
46 | gettimeofday(&t0, 0); | |
47 | kid = fork(); if (kid < 0) lose("fork failed: %s", strerror(errno)); | |
48 | if (!kid) { | |
49 | execvp(argv[1], argv + 1); | |
50 | lose("exec (`%s') failed: %s", argv[1], strerror(errno)); | |
51 | } | |
52 | if (wait4(kid, &st, 0, &ru) < 0) lose("wait failed: %s", strerror(errno)); | |
53 | gettimeofday(&t1, 0); | |
54 | if (st) { | |
55 | if (WIFSIGNALED(st)) | |
56 | lose("program killed by signal %d\n", WTERMSIG(st)); | |
57 | else if (WIFEXITED(st)) | |
58 | lose("program failed with status %d\n", WEXITSTATUS(st)); | |
59 | else | |
60 | lose("program exited with incomprehensible status 0x%04x\n", st); | |
61 | } | |
62 | ||
63 | if (t0.tv_usec > t1.tv_usec) { | |
64 | t.tv_sec = t1.tv_sec - t0.tv_sec - 1; | |
65 | t.tv_usec = t1.tv_usec + 1000000 - t0.tv_usec; | |
66 | } else { | |
67 | t.tv_sec = t1.tv_sec - t0.tv_sec; | |
68 | t.tv_usec = t1.tv_usec - t0.tv_usec; | |
69 | } | |
70 | ||
71 | for (i = 1; i < argc; i++) { | |
72 | if (i > 1) fputc(' ', stderr); | |
73 | fputs(argv[i], stderr); | |
74 | } | |
75 | fprintf(stderr, ": elapsed = %.4fs; user = %.4fs; system = %.4fs\n", | |
76 | timeval_to_float(&t), | |
77 | timeval_to_float(&ru.ru_utime), | |
78 | timeval_to_float(&ru.ru_stime)); | |
79 | return (0); | |
80 | } |