From b69ec3f6d953e67422dd32b72688cba850fd1b2e Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Mon, 13 Jan 2014 15:56:57 -0800 Subject: Initial commit --- src/timing.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/timing.c (limited to 'src/timing.c') diff --git a/src/timing.c b/src/timing.c new file mode 100644 index 0000000..25cbba7 --- /dev/null +++ b/src/timing.c @@ -0,0 +1,86 @@ +/* timing.c -- cross-platform wall time + * Copyright (C) 2013 Galois, Inc. All rights reserved. */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#define _POSIX_C_SOURCE 199309L + +#include + +#include "timing.h" +#include "require.h" + +#define ignore(var) ((void)(var)) + +const uint64_t MICRO_PER_BASE = 1000000; +const uint64_t NANO_PER_MICRO = 1000; + +// Try to use the POSIX timers, if possible. +#if HAVE_UNISTD_H +# include +#endif +#if (HAVE_UNISTD_H && _POSIX_TIMERS > 0) + +# include + +# if __linux__ + /* Hopefully, you're running linux >=2.6.28, and + * CLOCK_MONOTONIC_RAW exists. */ + static const clockid_t CLOCK_ID = CLOCK_MONOTONIC_RAW; +# elif _POSIX_MONOTONIC_CLOCK + // You're not on Linux, but you've got a POSIX monotonic clock. + static const clockid_t CLOCK_ID = CLOCK_MONOTONIC; +# else + // Just use the POSIX wall clock. + static const clockid_t CLOCK_ID = CLOCK_REALTIME; +# endif + + int timing_get_wall(uint64_t *const result) + { + int r = 0; + struct timespec now; + require_zero(clock_gettime(CLOCK_ID, &now), 1); + *result = (uint64_t)now.tv_sec * MICRO_PER_BASE + + (uint64_t)now.tv_nsec / NANO_PER_MICRO; + done: return r; + } + +#elif (__APPLE__ && __MACH__) + + /* No POSIX timers, but we're on a Mac, so we can use + * 'mach_absolute_time'. */ +# include + + int timing_get_wall(uint64_t *const result) + { + static mach_timebase_info_data_t timebase_info; + int r = 0; + *result = mach_absolute_time(); + /* *result is now in units of Mach ticks. Convert that to + * nanoseconds using the timebase information that Mach + * provides. Note that 'timebase_info' is static, so it got + * zeroed out at the start of the program run; if its + * denominator is still zero, we've definitely not stored + * anything in it yet. */ + if (timebase_info.denom == 0) { + require_zero(mach_timebase_info(&timebase_info), 1); + } + *result = *result * timebase_info.numer / timebase_info.denom; + // Convert nanoseconds to microseconds. + *result /= NANO_PER_MICRO; + done: return r; + } + +#else + + // I have no clue what wacky platform you're on. +# error Unsupported timing platform + + int timing_get_wall(uint64_t *const result) + { + ignore(result); + return -1; + } + +#endif -- cgit v1.2.3