Bug 3330205, 3362385 clock(3) SMP safety and epoch
Change-Id: Ida1e4400489c8c19818c6af5640ab89942c8f712
diff --git a/libc/unistd/time.c b/libc/unistd/time.c
index 13d7366..4b51675 100644
--- a/libc/unistd/time.c
+++ b/libc/unistd/time.c
@@ -42,21 +42,29 @@
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;
}