diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-04-26 11:17:48 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-04-26 12:01:48 -0400 |
commit | 9abf541f7f70068b6f7567481739ca6374f1fd57 (patch) | |
tree | 2d3feeaa192761116fb7eee48d1b8cde46b86a49 /src/common | |
parent | 7cbc44eeb19831bc467f8e1b87062ed1c87934d5 (diff) | |
download | tor-9abf541f7f70068b6f7567481739ca6374f1fd57.tar.gz tor-9abf541f7f70068b6f7567481739ca6374f1fd57.zip |
Add a function to compute millisecond time difference quickly.
Our main function, though accurate on all platforms, can be very
slow on 32-bit hosts. This one is faster on all 32-bit hosts, and
accurate everywhere except apple, where it will typically be off by
1%. But since 32-bit apple is a relic anyway, I think we should be
fine.
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/compat_time.c | 50 | ||||
-rw-r--r-- | src/common/compat_time.h | 27 |
2 files changed, 77 insertions, 0 deletions
diff --git a/src/common/compat_time.c b/src/common/compat_time.c index 966216768f..b3723f533c 100644 --- a/src/common/compat_time.c +++ b/src/common/compat_time.c @@ -279,6 +279,7 @@ monotime_reset_ratchets_for_testing(void) * nanoseconds. */ static struct mach_timebase_info mach_time_info; +static struct mach_timebase_info mach_time_info_msec_cvt; static int monotime_shift = 0; static void @@ -296,6 +297,14 @@ monotime_init_internal(void) // requires that tor_log2(0) == 0. monotime_shift = tor_log2(ms_per_tick); } + { + // For converting ticks to milliseconds in a 32-bit-friendly way, we + // will first right-shift by 20, and then multiply by 20/19, since + // (1<<20) * 19/20 is about 1e6. We precompute a new numerate and + // denominator here to avoid multiple multiplies. + mach_time_info_msec_cvt.numer = mach_time_info.numer * 20; + mach_time_info_msec_cvt.denom = mach_time_info.denom * 19; + } } /** @@ -345,6 +354,22 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; } +int32_t +monotime_coarse_diff_msec32_(const monotime_coarse_t *start, + const monotime_coarse_t *end) +{ + if (BUG(mach_time_info.denom == 0)) { + monotime_init(); + } + const int64_t diff_ticks = end->abstime_ - start->abstime_; + + /* We already require in di_ops.c that right-shift performs a sign-extend. */ + const int32_t diff_microticks = (int32_t)(diff_ticks >> 20); + + return (diff_microticks * mach_time_info_msec_cvt.numer) / + mach_time_info_msec_cvt.denom; +} + uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t) { @@ -443,6 +468,15 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; } +int32_t +monotime_coarse_diff_msec32_(const monotime_coarse_t *start, + const monotime_coarse_t *end) +{ + const int32_t diff_sec = (int32_t)(end->ts_.tv_sec - start->ts_.tv_sec); + const int32_t diff_nsec = (int32_t)(end->ts_.tv_nsec - start->ts_.tv_nsec); + return diff_sec * 1000 + diff_nsec / ONE_MILLION; +} + /* This value is ONE_BILLION >> 20. */ static const uint32_t STAMP_TICKS_PER_SECOND = 953; @@ -592,6 +626,13 @@ monotime_coarse_diff_msec(const monotime_coarse_t *start, return diff_ticks; } +int32_t +monotime_coarse_diff_msec32_(const monotime_coarse_t *start, + const monotime_coarse_t *end) +{ + return (int32_t)monotime_coarse_diff_msec(start, end) +} + int64_t monotime_coarse_diff_usec(const monotime_coarse_t *start, const monotime_coarse_t *end) @@ -677,6 +718,15 @@ monotime_diff_nsec(const monotime_t *start, return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000); } +int32_t +monotime_coarse_diff_msec32_(const monotime_coarse_t *start, + const monotime_coarse_t *end) +{ + struct timeval diff; + timersub(&end->tv_, &start->tv_, &diff); + return diff.tv_sec * 1000 + diff.tv_usec / 1000; +} + /* This value is ONE_MILLION >> 10. */ static const uint32_t STAMP_TICKS_PER_SECOND = 976; diff --git a/src/common/compat_time.h b/src/common/compat_time.h index 09dd6add3d..57ab20ab11 100644 --- a/src/common/compat_time.h +++ b/src/common/compat_time.h @@ -173,6 +173,33 @@ void monotime_coarse_add_msec(monotime_coarse_t *out, #define monotime_coarse_add_msec monotime_add_msec #endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */ +/** + * As monotime_coarse_diff_msec, but avoid 64-bit division. + * + * Requires that the difference fit into an int32_t; not for use with + * large time differences. + */ +int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start, + const monotime_coarse_t *end); + +/** + * As monotime_coarse_diff_msec, but avoid 64-bit division if it is expensive. + * + * Requires that the difference fit into an int32_t; not for use with + * large time differences. + */ +static inline int32_t +monotime_coarse_diff_msec32(const monotime_coarse_t *start, + const monotime_coarse_t *end) +{ +#if SIZEOF_VOID_P == 8 + // on a 64-bit platform, let's assume 64/64 division is cheap. + return (int32_t) monotime_coarse_diff_msec(start, end); +#else + return monotime_coarse_diff_msec32_(start, end); +#endif +} + MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval)); #ifdef TOR_UNIT_TESTS |