#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(); }