diff --git a/libc/unistd/time.c b/libc/unistd/time.c index 13d73661a..4b51675f3 100644 --- a/libc/unistd/time.c +++ b/libc/unistd/time.c @@ -42,21 +42,29 @@ time(time_t *t) return (tt.tv_sec); } +// return monotonically increasing CPU time in ticks relative to unspecified epoch +static inline clock_t clock_now(void) +{ + struct timespec tm; + clock_gettime( CLOCK_MONOTONIC, &tm); + return tm.tv_sec * CLOCKS_PER_SEC + (tm.tv_nsec * (CLOCKS_PER_SEC/1e9)); +} +// initialized by the constructor below +static clock_t clock_start; + +// called by dlopen when .so is loaded +__attribute__((constructor)) static void clock_crt0(void) +{ + clock_start = clock_now(); +} + +// return elapsed CPU time in clock ticks, since start of program execution +// (spec says epoch is undefined, but glibc uses crt0 as epoch) clock_t clock(void) { - struct timespec tm; - static int clock_inited; - static clock_t clock_start; - clock_t now; - - clock_gettime( CLOCK_MONOTONIC, &tm); - now = tm.tv_sec * CLOCKS_PER_SEC + (tm.tv_nsec * (CLOCKS_PER_SEC/1e9)); - - if (!clock_inited) { - clock_start = now; - clock_inited = 1; - } - return now - clock_start; + // note that if we are executing in a different thread than crt0, then the + // pthread_create that made us had a memory barrier so clock_start is defined + return clock_now() - clock_start; }