diff options
author | Matt Johnston <matt@ucc.asn.au> | 2014-03-13 23:50:09 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2014-03-13 23:50:09 +0800 |
commit | e767bbb41f277ebb8f477e5cda5b97a3a52b08a7 (patch) | |
tree | 79e85d770254e5a929aa6d3e09974cbf1fdd6d2e /dbutil.c | |
parent | 2b599df57abf70963706b62604ecc2c421b549da (diff) |
Add new monotonic_now() wrapper so that timeouts are unaffected by
system clock changes
Diffstat (limited to 'dbutil.c')
-rw-r--r-- | dbutil.c | 43 |
1 files changed, 43 insertions, 0 deletions
@@ -48,6 +48,19 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "config.h" + +#ifdef __linux__ +#define _GNU_SOURCE +/* To call clock_gettime() directly */ +#include <sys/syscall.h> +#endif /* __linux */ + +#ifdef HAVE_MACH_MACH_TIME_H +#include <mach/mach_time.h> +#include <mach/mach.h> +#endif + #include "includes.h" #include "dbutil.h" #include "buffer.h" @@ -932,3 +945,33 @@ int constant_time_memcmp(const void* a, const void *b, size_t n) return c; } +time_t monotonic_now() { + +#if defined(__linux__) && defined(SYS_clock_gettime) + /* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32. Probably cheaper. */ +#ifndef CLOCK_MONOTONIC_COARSE +#define CLOCK_MONOTONIC_COARSE 6 +#endif + static clockid_t clock_source = CLOCK_MONOTONIC_COARSE; + struct timespec ts; + + if (syscall(SYS_clock_gettime, clock_source, &ts) == EINVAL) { + clock_source = CLOCK_MONOTONIC; + syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts); + } + return ts.tv_sec; +#elif defined(HAVE_MACH_ABSOLUTE_TIME) + /* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */ + mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); + } + return mach_absolute_time() * timebase_info.numer / timebase_info.denom + / 1e9; +#else + /* Fallback for everything else - this will sometimes go backwards */ + return time(NULL); +#endif + +} + |