diff options
Diffstat (limited to 'src/common/compat_time.c')
-rw-r--r-- | src/common/compat_time.c | 227 |
1 files changed, 205 insertions, 22 deletions
diff --git a/src/common/compat_time.c b/src/common/compat_time.c index d044bbe1d7..183a60a480 100644 --- a/src/common/compat_time.c +++ b/src/common/compat_time.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2016, The Tor Project, Inc. */ + * Copyright (c) 2007-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -28,7 +28,7 @@ /* as fallback implementation for tor_sleep_msec */ #include <sys/select.h> #endif -#endif +#endif /* defined(TOR_UNIT_TESTS) */ #ifdef __APPLE__ #include <mach/mach_time.h> @@ -64,9 +64,9 @@ tor_sleep_msec(int msec) select(0, NULL, NULL, NULL, &tv); #else sleep(CEIL_DIV(msec, 1000)); -#endif +#endif /* defined(_WIN32) || ... */ } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ /** Set *timeval to the current time of day. On error, log and terminate. * (Same as gettimeofday(timeval,NULL), but never returns -1.) @@ -90,7 +90,7 @@ tor_gettimeofday(struct timeval *timeval) if (ft.ft_64 < EPOCH_BIAS) { /* LCOV_EXCL_START */ log_err(LD_GENERAL,"System time is before 1970; failing."); - exit(1); + exit(1); // exit ok: system clock is broken. /* LCOV_EXCL_STOP */ } ft.ft_64 -= EPOCH_BIAS; @@ -102,7 +102,7 @@ tor_gettimeofday(struct timeval *timeval) log_err(LD_GENERAL,"gettimeofday failed."); /* If gettimeofday dies, we have either given a bad timezone (we didn't), or segfaulted.*/ - exit(1); + exit(1); // exit ok: gettimeofday failed. /* LCOV_EXCL_STOP */ } #elif defined(HAVE_FTIME) @@ -112,7 +112,7 @@ tor_gettimeofday(struct timeval *timeval) timeval->tv_usec = tb.millitm * 1000; #else #error "No way to get time." -#endif +#endif /* defined(_WIN32) || ... */ return; } @@ -187,8 +187,8 @@ monotime_coarse_set_mock_time_nsec(int64_t nsec) tor_assert_nonfatal(monotime_mocking_enabled == 1); mock_time_nsec_coarse = nsec; } -#endif -#endif +#endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ +#endif /* defined(TOR_UNIT_TESTS) */ /* "ratchet" functions for monotonic time. */ @@ -235,7 +235,7 @@ ratchet_coarse_performance_counter(const int64_t count_raw) last_tick_count = count; return count; } -#endif +#endif /* defined(_WIN32) || defined(TOR_UNIT_TESTS) */ #if defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS) static struct timeval last_timeofday = { 0, 0 }; @@ -251,7 +251,7 @@ ratchet_timeval(const struct timeval *timeval_raw, struct timeval *out) { /* must hold lock */ timeradd(timeval_raw, &timeofday_offset, out); - if (PREDICT_UNLIKELY(timercmp(out, &last_timeofday, <))) { + if (PREDICT_UNLIKELY(timercmp(out, &last_timeofday, OP_LT))) { /* time ran backwards. Instead, declare that no time occurred. */ timersub(&last_timeofday, timeval_raw, &timeofday_offset); memcpy(out, &last_timeofday, sizeof(struct timeval)); @@ -259,7 +259,7 @@ ratchet_timeval(const struct timeval *timeval_raw, struct timeval *out) memcpy(&last_timeofday, out, sizeof(struct timeval)); } } -#endif +#endif /* defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS) */ #ifdef TOR_UNIT_TESTS /** For testing: reset all the ratchets */ @@ -271,7 +271,7 @@ monotime_reset_ratchets_for_testing(void) memset(&last_timeofday, 0, sizeof(struct timeval)); memset(&timeofday_offset, 0, sizeof(struct timeval)); } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ #ifdef __APPLE__ @@ -279,6 +279,7 @@ monotime_reset_ratchets_for_testing(void) * nanoseconds. */ static struct mach_timebase_info mach_time_info; +static int monotime_shift = 0; static void monotime_init_internal(void) @@ -287,6 +288,14 @@ monotime_init_internal(void) int r = mach_timebase_info(&mach_time_info); tor_assert(r == 0); tor_assert(mach_time_info.denom != 0); + + { + // approximate only. + uint64_t ns_per_tick = mach_time_info.numer / mach_time_info.denom; + uint64_t ms_per_tick = ns_per_tick * ONE_MILLION; + // requires that tor_log2(0) == 0. + monotime_shift = tor_log2(ms_per_tick); + } } /** @@ -301,10 +310,25 @@ monotime_get(monotime_t *out) / mach_time_info.numer; return; } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ out->abstime_ = mach_absolute_time(); } +#if defined(HAVE_MACH_APPROXIMATE_TIME) +void +monotime_coarse_get(monotime_coarse_t *out) +{ +#ifdef TOR_UNIT_TESTS + if (monotime_mocking_enabled) { + out->abstime_ = (mock_time_nsec_coarse * mach_time_info.denom) + / mach_time_info.numer; + return; + } +#endif /* defined(TOR_UNIT_TESTS) */ + out->abstime_ = mach_approximate_time(); +} +#endif + /** * Return the number of nanoseconds between <b>start</b> and <b>end</b>. */ @@ -321,6 +345,26 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; } +uint32_t +monotime_coarse_to_stamp(const monotime_coarse_t *t) +{ + return (uint32_t)(t->abstime_ >> monotime_shift); +} + +int +monotime_is_zero(const monotime_t *val) +{ + return val->abstime_ == 0; +} + +void +monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec) +{ + const uint64_t nsec = msec * ONE_MILLION; + const uint64_t ticks = (nsec * mach_time_info.denom) / mach_time_info.numer; + out->abstime_ = val->abstime_ + ticks; +} + /* end of "__APPLE__" */ #elif defined(HAVE_CLOCK_GETTIME) @@ -332,7 +376,7 @@ monotime_diff_nsec(const monotime_t *start, * an old Linux kernel. In that case, we will fall back to CLOCK_MONOTONIC. */ static int clock_monotonic_coarse = CLOCK_MONOTONIC_COARSE; -#endif +#endif /* defined(CLOCK_MONOTONIC_COARSE) */ static void monotime_init_internal(void) @@ -344,7 +388,7 @@ monotime_init_internal(void) "falling back to CLOCK_MONOTONIC.", strerror(errno)); clock_monotonic_coarse = CLOCK_MONOTONIC; } -#endif +#endif /* defined(CLOCK_MONOTONIC_COARSE) */ } void @@ -356,7 +400,7 @@ monotime_get(monotime_t *out) out->ts_.tv_nsec = (int) (mock_time_nsec % ONE_BILLION); return; } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ int r = clock_gettime(CLOCK_MONOTONIC, &out->ts_); tor_assert(r == 0); } @@ -371,7 +415,7 @@ monotime_coarse_get(monotime_coarse_t *out) out->ts_.tv_nsec = (int) (mock_time_nsec_coarse % ONE_BILLION); return; } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ int r = clock_gettime(clock_monotonic_coarse, &out->ts_); if (PREDICT_UNLIKELY(r < 0) && errno == EINVAL && @@ -386,7 +430,7 @@ monotime_coarse_get(monotime_coarse_t *out) tor_assert(r == 0); } -#endif +#endif /* defined(CLOCK_MONOTONIC_COARSE) */ int64_t monotime_diff_nsec(const monotime_t *start, @@ -399,6 +443,37 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; } +/* This value is ONE_BILLION >> 20. */ +static const uint32_t STAMP_TICKS_PER_SECOND = 953; + +uint32_t +monotime_coarse_to_stamp(const monotime_coarse_t *t) +{ + uint32_t nsec = (uint32_t)t->ts_.tv_nsec; + uint32_t sec = (uint32_t)t->ts_.tv_sec; + + return (sec * STAMP_TICKS_PER_SECOND) + (nsec >> 20); +} + +int +monotime_is_zero(const monotime_t *val) +{ + return val->ts_.tv_sec == 0 && val->ts_.tv_nsec == 0; +} + +void +monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec) +{ + const uint32_t sec = msec / 1000; + const uint32_t msec_remainder = msec % 1000; + out->ts_.tv_sec = val->ts_.tv_sec + sec; + out->ts_.tv_nsec = val->ts_.tv_nsec + (msec_remainder * ONE_MILLION); + if (out->ts_.tv_nsec > ONE_BILLION) { + out->ts_.tv_nsec -= ONE_BILLION; + out->ts_.tv_sec += 1; + } +} + /* end of "HAVE_CLOCK_GETTIME" */ #elif defined (_WIN32) @@ -462,7 +537,7 @@ monotime_get(monotime_t *out) / nsec_per_tick_numer; return; } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ /* Alas, QueryPerformanceCounter is not always monotonic: see bug list at @@ -486,7 +561,7 @@ monotime_coarse_get(monotime_coarse_t *out) out->tick_count_ = mock_time_nsec_coarse / ONE_MILLION; return; } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ if (GetTickCount64_fn) { out->tick_count_ = (int64_t)GetTickCount64_fn(); @@ -531,6 +606,41 @@ monotime_coarse_diff_nsec(const monotime_coarse_t *start, return monotime_coarse_diff_msec(start, end) * ONE_MILLION; } +static const uint32_t STAMP_TICKS_PER_SECOND = 1000; + +uint32_t +monotime_coarse_to_stamp(const monotime_coarse_t *t) +{ + return (uint32_t) t->tick_count_; +} + +int +monotime_is_zero(const monotime_t *val) +{ + return val->pcount_ == 0; +} + +int +monotime_coarse_is_zero(const monotime_coarse_t *val) +{ + return val->tick_count_ == 0; +} + +void +monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec) +{ + const uint64_t nsec = msec * ONE_MILLION; + const uint64_t ticks = (nsec * nsec_per_tick_denom) / nsec_per_tick_numer; + out->pcount_ = val->pcount_ + ticks; +} + +void +monotime_coarse_add_msec(monotime_coarse_t *out, const monotime_coarse_t *val, + uint32_t msec) +{ + out->tick_count_ = val->tick_count_ + msec; +} + /* end of "_WIN32" */ #elif defined(MONOTIME_USING_GETTIMEOFDAY) @@ -567,10 +677,40 @@ monotime_diff_nsec(const monotime_t *start, return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000); } +/* This value is ONE_MILLION >> 10. */ +static const uint32_t STAMP_TICKS_PER_SECOND = 976; + +uint32_t +monotime_coarse_to_stamp(const monotime_coarse_t *t) +{ + const uint32_t usec = (uint32_t)t->tv_.tv_usec; + const uint32_t sec = (uint32_t)t->tv_.tv_sec; + return (sec * STAMP_TICKS_PER_SECOND) | (nsec >> 10); +} + +int +monotime_is_zero(const monotime_t *val) +{ + return val->tv_.tv_sec == 0 && val->tv_.tv_usec == 0; +} + +void +monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec) +{ + const uint32_t sec = msec / 1000; + const uint32_t msec_remainder = msec % 1000; + out->tv_.tv_sec = val->tv_.tv_sec + sec; + out->tv_.tv_usec = val->tv_.tv_nsec + (msec_remainder * 1000); + if (out->tv_.tv_usec > ONE_MILLION) { + out->tv_.tv_usec -= ONE_MILLION; + out->tv_.tv_sec += 1; + } +} + /* end of "MONOTIME_USING_GETTIMEOFDAY" */ #else #error "No way to implement monotonic timers." -#endif +#endif /* defined(__APPLE__) || ... */ /** * Initialize the monotonic timer subsystem. Must be called before any @@ -589,6 +729,19 @@ monotime_init(void) } } +void +monotime_zero(monotime_t *out) +{ + memset(out, 0, sizeof(*out)); +} +#ifdef MONOTIME_COARSE_TYPE_IS_DIFFERENT +void +monotime_coarse_zero(monotime_coarse_t *out) +{ + memset(out, 0, sizeof(*out)); +} +#endif + int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end) @@ -653,5 +806,35 @@ monotime_coarse_absolute_msec(void) { return monotime_coarse_absolute_nsec() / ONE_MILLION; } +#else +#define initialized_at_coarse initialized_at +#endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ + +/** + * Return the current time "stamp" as described by monotime_coarse_to_stamp. + */ +uint32_t +monotime_coarse_get_stamp(void) +{ + monotime_coarse_t now; + monotime_coarse_get(&now); + return monotime_coarse_to_stamp(&now); +} + +#ifdef __APPLE__ +uint64_t +monotime_coarse_stamp_units_to_approx_msec(uint64_t units) +{ + /* Recover as much precision as we can. */ + uint64_t abstime_diff = (units << monotime_shift); + return (abstime_diff * mach_time_info.numer) / + (mach_time_info.denom * ONE_MILLION); +} +#else +uint64_t +monotime_coarse_stamp_units_to_approx_msec(uint64_t units) +{ + return (units * 1000) / STAMP_TICKS_PER_SECOND; +} #endif |