aboutsummaryrefslogtreecommitdiffstats
path: root/usr/time.c
blob: c97fb3466157dbd6c1182edc2838037c61f3a35b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "gbos.h"
/* time CMD [ARGS]: run a command and report how long it took.
 *
 * Reads the kernel's 64 Hz tick before and after, so the resolution is 1/64s.
 * The child's command line has to be rebuilt at $A000 ("cmd\0args\0", the
 * shape usr/sh.c leaves) - which is also OUR argument area, so everything is
 * copied to the stack first. */

#define ARGV0 ((char *)0xA000)

static void two(unsigned int v) {
    if (v < 10) putc('0');
    putu(v);
}

void main(void) {
    char args[64];
    char *cmd, *rest;
    unsigned char t0[4], t1[4], id, i, j;
    unsigned long ticks;
    unsigned int sec, hund;
    union {
        unsigned long l;
        unsigned char b[4];
    } u;

    {
        char *a = getargs();
        for (i = 0; a[i] && i < 63; i++) args[i] = a[i];
        args[i] = 0;
    }
    if (!args[0]) {
        puts("usage: time CMD [ARGS]");
        nl();
        sexit(2);
    }

    cmd = args; /* split "cmd rest..." */
    i = 0;
    while (args[i] && args[i] != ' ') i++;
    rest = args + i;
    if (args[i]) {
        args[i] = 0;
        rest = args + i + 1;
    }

    id = lookup(cmd);
    if (id == NOFD) {
        puts(cmd);
        puts(": not found");
        nl();
        sexit(127);
    }

    gticks(t0);
    {
        char *p = ARGV0; /* rebuild the child's command line */
        for (j = 0; cmd[j]; j++) *p++ = cmd[j];
        *p++ = 0;
        for (j = 0; rest[j]; j++) *p++ = rest[j];
        *p = 0;
    }
    if (fork() == 0) exec(id);
    wait();
    gticks(t1);

    /* elapsed ticks, 32-bit, little-endian - no long division (see uptime.c) */
    u.b[0] = t1[0];
    u.b[1] = t1[1];
    u.b[2] = t1[2];
    u.b[3] = t1[3];
    ticks = u.l;
    u.b[0] = t0[0];
    u.b[1] = t0[1];
    u.b[2] = t0[2];
    u.b[3] = t0[3];
    ticks -= u.l;

    sec = 0;
    while (ticks >= 64UL) {
        ticks -= 64UL;
        sec++;
    }
    hund = 0;                                                /* remaining ticks -> hundredths */
    while (ticks--) hund += 2;                               /* 1/64 s ~ 0.0156 s ~ 1.56/100 */
    hund = (unsigned int)(hund - (hund >> 2) - (hund >> 4)); /* ~x1.5625/2 */

    puts("real ");
    putu(sec);
    putc('.');
    two(hund > 99 ? 99 : hund);
    puts("s");
    nl();
}