X-Git-Url: https://unix4lyfe.org/gitweb/darkstat/blobdiff_plain/1b1591ab5dc81e7aa2cb2665d034572f5157e0e1..0736c704e88399324e1a3c5d484cb116458c23b1:/now.c diff --git a/now.c b/now.c index ffc1433..b1a43cb 100644 --- a/now.c +++ b/now.c @@ -1,5 +1,5 @@ /* darkstat 3 - * copyright (c) 2012 Emil Mikulic. + * copyright (c) 2012-2014 Emil Mikulic. * * now.c: a cache of the current time. * @@ -17,20 +17,58 @@ */ #include "err.h" #include "now.h" +#include "str.h" #include #include #include +#if defined(__MACH__) && !defined(__gnu_hurd__) +/* Fake up clock_gettime() on OS X. */ +# include +# include +# include +# include + + typedef int clockid_t; +# define CLOCK_REALTIME 0 +# define CLOCK_MONOTONIC 1 + + static uint64_t mono_first = 0; + + int clock_gettime(clockid_t clk_id, struct timespec *tp) { + if (clk_id == CLOCK_REALTIME) { + struct timeval tv; + gettimeofday(&tv, NULL); + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * 1000; + return 0; + } + if (clk_id == CLOCK_MONOTONIC) { + uint64_t t = mach_absolute_time(); + mach_timebase_info_data_t timebase; + mach_timebase_info(&timebase); + if (!mono_first) { + mono_first = t; + } + uint64_t tdiff = (t - mono_first) * timebase.numer / timebase.denom; + tp->tv_sec = tdiff / 1000000000; + tp->tv_nsec = tdiff % 1000000000; + return 0; + } + return -1; + } +#endif /* __MACH__ */ + static struct timespec clock_real, clock_mono; static int now_initialized = 0; -long now_real(void) { +time_t now_real(void) { assert(now_initialized); return clock_real.tv_sec; } -long now_mono(void) { +time_t now_mono(void) { assert(now_initialized); return clock_mono.tv_sec; } @@ -43,6 +81,17 @@ static int before(const struct timespec *a, const struct timespec *b) { return 0; } +static void warn_backwards(const char *name, + const struct timespec * const t0, + const struct timespec * const t1) { + verbosef("%s clock went backwards from %lld.%09lld to %lld.%09lld", + name, + (lld)t0->tv_sec, + (lld)t0->tv_nsec, + (lld)t1->tv_sec, + (lld)t1->tv_nsec); +} + static void clock_update(const clockid_t clk_id, struct timespec *dest, const char *name) { @@ -50,12 +99,7 @@ static void clock_update(const clockid_t clk_id, clock_gettime(clk_id, &t); if (now_initialized && before(&t, dest)) { - verbosef("%s clock went backwards from %ld.%09ld to %ld.%09ld", - name, - (long)dest->tv_sec, - (long)dest->tv_nsec, - (long)t.tv_sec, - (long)t.tv_nsec); + warn_backwards(name, &t, dest); } memcpy(dest, &t, sizeof(t)); } @@ -76,14 +120,44 @@ void now_update(void) { all_clocks_update(); } -long mono_to_real(const long t) { +time_t mono_to_real(const int64_t t) { assert(now_initialized); - return t - clock_mono.tv_sec + clock_real.tv_sec; + return (time_t)(t - (int64_t)clock_mono.tv_sec + (int64_t)clock_real.tv_sec); } -long real_to_mono(const long t) { +int64_t real_to_mono(const time_t t) { assert(now_initialized); - return t - clock_real.tv_sec + clock_mono.tv_sec; + return (int64_t)(t - clock_real.tv_sec + clock_mono.tv_sec); +} + +void timer_start(struct timespec *t) { + clock_gettime(CLOCK_MONOTONIC, t); +} + +static int64_t ts_diff(const struct timespec * const a, + const struct timespec * const b) { + return (int64_t)(a->tv_sec - b->tv_sec) * 1000000000 + + a->tv_nsec - b->tv_nsec; +} + +void timer_stop(const struct timespec * const t0, + const int64_t nsec, + const char *warning) { + struct timespec t1; + int64_t diff; + + clock_gettime(CLOCK_MONOTONIC, &t1); + if (before(&t1, t0)) { + warn_backwards("monotonic timer", t0, &t1); + return; + } + diff = ts_diff(&t1, t0); + if (diff > nsec) { + warnx("%s (took %lld nsec, over threshold of %lld nsec)", + warning, + (lld)diff, + (lld)nsec); + } } /* vim:set ts=3 sw=3 tw=80 et: */