diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-07-08 12:53:51 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-07-19 11:40:46 +0200 |
commit | dc6f5d1dc1ccc86f32b39b939a5f83c35865d666 (patch) | |
tree | 2af4197a9440c5f5ddc39152c8f029f6df2bf340 /src/common/compat_time.h | |
parent | aa971c59246332391116caafd18855bccf2f99a5 (diff) | |
download | tor-dc6f5d1dc1ccc86f32b39b939a5f83c35865d666.tar.gz tor-dc6f5d1dc1ccc86f32b39b939a5f83c35865d666.zip |
Basic portable monotonic timer implementation
This code uses QueryPerformanceCounter() [**] on Windows,
mach_absolute_time() on OSX, clock_gettime() where available, and
gettimeofday() [*] elsewhere.
Timer types are stored in an opaque OS-specific format; the only
supported operation is to compute the difference between two timers.
[*] As you know, gettimeofday() isn't monotonic, so we include
a simple ratchet function to ensure that it only moves forward.
[**] As you may not know, QueryPerformanceCounter() isn't actually
always as monotonic as you might like it to be, so we ratchet that
one too.
We also include a "coarse monotonic timer" for cases where we don't
actually need high-resolution time. This is GetTickCount{,64}() on
Windows, clock_gettime(CLOCK_MONOTONIC_COARSE) on Linux, and falls
back to regular monotonic time elsewhere.
Diffstat (limited to 'src/common/compat_time.h')
-rw-r--r-- | src/common/compat_time.h | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/common/compat_time.h b/src/common/compat_time.h index 56126ba84c..d69af8f98c 100644 --- a/src/common/compat_time.h +++ b/src/common/compat_time.h @@ -3,11 +3,28 @@ * Copyright (c) 2007-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * \file compat_time.h + * + * \brief Functions and types for monotonic times. + * + * monotime_* functions try to provide a high-resolution monotonic timer with + * something the best resolution the system provides. monotime_coarse_* + * functions run faster (if the operating system gives us a way to do that) + * but produce a less accurate timer: accuracy will probably be on the order + * of tens of milliseconds. + */ + #ifndef TOR_COMPAT_TIME_H #define TOR_COMPAT_TIME_H #include "orconfig.h" +#if defined(HAVE_CLOCK_GETTIME) +/* to ensure definition of CLOCK_MONOTONIC_COARSE if it's there */ +#include <time.h> +#endif + #if !defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) /** Implementation of timeval for platforms that don't have it. */ struct timeval { @@ -16,11 +33,115 @@ struct timeval { }; #endif +/** Represents a monotonic timer in a platform-dependent way. */ +typedef struct monotime_t { +#ifdef __APPLE__ + /* On apple, there is a 64-bit counter whose precision we must look up. */ + uint64_t abstime_; +#elif defined(HAVE_CLOCK_GETTIME) + /* It sure would be nice to use clock_gettime(). Posix is a nice thing. */ + struct timespec ts_; +#elif defined (_WIN32) + /* On Windows, there is a 64-bit counter whose precision we must look up. */ + int64_t pcount_; +#else +#define MONOTIME_USING_GETTIMEOFDAY + /* Otherwise, we will be stuck using gettimeofday. */ + struct timeval tv_; +#endif +} monotime_t; + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC_COARSE) +#define MONOTIME_COARSE_FN_IS_DIFFERENT +#define monotime_coarse_t monotime_t +#elif defined(_WIN32) +#define MONOTIME_COARSE_FN_IS_DIFFERENT +#define MONOTIME_COARSE_TYPE_IS_DIFFERENT +/** Represents a coarse monotonic time in a platform-independent way. */ +typedef struct monotime_coarse_t { + uint64_t tick_count_; +} monotime_coarse_t; +#else +#define monotime_coarse_t monotime_t +#endif + +/** + * Initialize the timing subsystem. This function is idempotent. + */ +void monotime_init(void); +/** + * Set <b>out</b> to the current time. + */ +void monotime_get(monotime_t *out); +/** + * Return the number of nanoseconds between <b>start</b> and <b>end</b>. + */ +int64_t monotime_diff_nsec(const monotime_t *start, const monotime_t *end); +/** + * Return the number of microseconds between <b>start</b> and <b>end</b>. + */ +int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end); +/** + * Return the number of milliseconds between <b>start</b> and <b>end</b>. + */ +int64_t monotime_diff_msec(const monotime_t *start, const monotime_t *end); +/** + * Return the number of nanoseconds since the timer system was initialized. + */ +uint64_t monotime_absolute_nsec(void); +/** + * Return the number of microseconds since the timer system was initialized. + */ +uint64_t monotime_absolute_usec(void); +/** + * Return the number of milliseconds since the timer system was initialized. + */ +uint64_t monotime_absolute_msec(void); + +#if defined(MONOTIME_COARSE_FN_IS_DIFFERENT) +/** + * Set <b>out</b> to the current coarse time. + */ +void monotime_coarse_get(monotime_coarse_t *out); +uint64_t monotime_coarse_absolute_nsec(void); +uint64_t monotime_coarse_absolute_usec(void); +uint64_t monotime_coarse_absolute_msec(void); +#else +#define monotime_coarse_get monotime_get +#define monotime_coarse_absolute_nsec monotime_absolute_nsec +#define monotime_coarse_absolute_usec monotime_absolute_usec +#define monotime_coarse_absolute_msec monotime_absolute_msec +#endif + +#if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) +int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start, + const monotime_coarse_t *end); +int64_t monotime_coarse_diff_usec(const monotime_coarse_t *start, + const monotime_coarse_t *end); +int64_t monotime_coarse_diff_msec(const monotime_coarse_t *start, + const monotime_coarse_t *end); +#else +#define monotime_coarse_diff_nsec monotime_diff_nsec +#define monotime_coarse_diff_usec monotime_diff_usec +#define monotime_coarse_diff_msec monotime_diff_msec +#endif + void tor_gettimeofday(struct timeval *timeval); #ifdef TOR_UNIT_TESTS void tor_sleep_msec(int msec); #endif +#ifdef COMPAT_TIME_PRIVATE +#ifdef _WIN32 +STATIC int64_t ratchet_performance_counter(int64_t count_raw); +STATIC int64_t ratchet_coarse_performance_counter(int64_t count_raw); +#endif +#ifdef MONOTIME_USING_GETTIMEOFDAY +STATIC void ratchet_timeval(const struct timeval *timeval_raw, + struct timeval *out); +#endif +#endif + #endif |