commit a097ddb4f5105d33146eb8f6afa7d6cd01d47fea
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Jun 28 12:57:01 2018 -0400
Extract time functionality into lib/wallclock and lib/time
---
.gitignore | 2 +
Makefile.am | 2 +
src/common/compat.h | 43 +--------
src/common/include.am | 2 -
src/common/util.c | 146 -------------------------------
src/common/util.h | 3 -
src/include.am | 1 +
src/lib/time/.may_include | 8 ++
src/{common => lib/time}/compat_time.c | 16 +++-
src/{common => lib/time}/compat_time.h | 2 +
src/lib/time/include.am | 19 ++++
src/lib/time/tvdiff.c | 155 +++++++++++++++++++++++++++++++++
src/lib/time/tvdiff.h | 16 ++++
src/lib/wallclock/include.am | 1 +
src/lib/wallclock/timeval.c | 0
src/lib/wallclock/timeval.h | 58 ++++++++++++
src/or/circuitstats.c | 1 +
src/or/circuituse.c | 1 +
src/or/geoip.c | 1 +
src/test/test_util.c | 1 +
20 files changed, 281 insertions(+), 197 deletions(-)
diff --git a/.gitignore b/.gitignore
index c940166aa..0b45af3b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -203,6 +203,8 @@ uptime-*.json
/src/lib/libtor-smartlist-core-testing.a
/src/lib/libtor-thread.a
/src/lib/libtor-thread-testing.a
+/src/lib/libtor-time.a
+/src/lib/libtor-time-testing.a
/src/lib/libtor-tls.a
/src/lib/libtor-tls-testing.a
/src/lib/libtor-trace.a
diff --git a/Makefile.am b/Makefile.am
index 5a7271e30..d28eb6149 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,7 @@ TOR_UTIL_LIBS = \
src/lib/libtor-thread.a \
src/lib/libtor-memarea.a \
src/lib/libtor-math.a \
+ src/lib/libtor-time.a \
src/lib/libtor-log.a \
src/lib/libtor-lock.a \
src/lib/libtor-fdio.a \
@@ -73,6 +74,7 @@ TOR_UTIL_TESTING_LIBS = \
src/lib/libtor-thread-testing.a \
src/lib/libtor-memarea-testing.a \
src/lib/libtor-math-testing.a \
+ src/lib/libtor-time-testing.a \
src/lib/libtor-log-testing.a \
src/lib/libtor-lock-testing.a \
src/lib/libtor-fdio-testing.a \
diff --git a/src/common/compat.h b/src/common/compat.h
index 5cd8e7215..582945734 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -59,54 +59,13 @@
#include "lib/fs/files.h"
#include "lib/fs/mmap.h"
#include "lib/fs/userdb.h"
+#include "lib/wallclock/timeval.h"
#include <stdio.h>
#include <errno.h>
/* ===== Time compatibility */
-#ifndef timeradd
-/** Replacement for timeradd on platforms that do not have it: sets tvout to
- * the sum of tv1 and tv2. */
-#define timeradd(tv1,tv2,tvout) \
- do { \
- (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec; \
- (tvout)->tv_usec = (tv1)->tv_usec + (tv2)->tv_usec; \
- if ((tvout)->tv_usec >= 1000000) { \
- (tvout)->tv_usec -= 1000000; \
- (tvout)->tv_sec++; \
- } \
- } while (0)
-#endif /* !defined(timeradd) */
-
-#ifndef timersub
-/** Replacement for timersub on platforms that do not have it: sets tvout to
- * tv1 minus tv2. */
-#define timersub(tv1,tv2,tvout) \
- do { \
- (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec; \
- (tvout)->tv_usec = (tv1)->tv_usec - (tv2)->tv_usec; \
- if ((tvout)->tv_usec < 0) { \
- (tvout)->tv_usec += 1000000; \
- (tvout)->tv_sec--; \
- } \
- } while (0)
-#endif /* !defined(timersub) */
-
-#ifndef timercmp
-/** Replacement for timercmp on platforms that do not have it: returns true
- * iff the relational operator "op" makes the expression tv1 op tv2 true.
- *
- * Note that while this definition should work for all boolean operators, some
- * platforms' native timercmp definitions do not support >=, <=, or ==. So
- * don't use those.
- */
-#define timercmp(tv1,tv2,op) \
- (((tv1)->tv_sec == (tv2)->tv_sec) ? \
- ((tv1)->tv_usec op (tv2)->tv_usec) : \
- ((tv1)->tv_sec op (tv2)->tv_sec))
-#endif /* !defined(timercmp) */
-
/* ===== File compatibility */
/* ===== Net compatibility */
diff --git a/src/common/include.am b/src/common/include.am
index 2d7297665..bb1a3ee42 100644
--- a/src/common/include.am
+++ b/src/common/include.am
@@ -27,7 +27,6 @@ LIBOR_A_SRC = \
src/common/address_set.c \
src/common/buffers.c \
src/common/compat.c \
- src/common/compat_time.c \
src/common/util.c \
src/common/token_bucket.c \
src/common/workqueue.c \
@@ -64,7 +63,6 @@ COMMONHEADERS = \
src/common/buffers.h \
src/common/compat.h \
src/common/compat_libevent.h \
- src/common/compat_time.h \
src/common/handles.h \
src/common/procmon.h \
src/common/timers.h \
diff --git a/src/common/util.c b/src/common/util.c
index e1fae0dea..b31bb834e 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -135,152 +135,6 @@ ENABLE_GCC_WARNING(aggregate-return)
* Time
* ===== */
-#define TOR_USEC_PER_SEC 1000000
-
-/** Return the difference between start->tv_sec and end->tv_sec.
- * Returns INT64_MAX on overflow and underflow.
- */
-static int64_t
-tv_secdiff_impl(const struct timeval *start, const struct timeval *end)
-{
- const int64_t s = (int64_t)start->tv_sec;
- const int64_t e = (int64_t)end->tv_sec;
-
- /* This may not be the most efficient way of implemeting this check,
- * but it's easy to see that it's correct and doesn't overflow */
-
- if (s > 0 && e < INT64_MIN + s) {
- /* s is positive: equivalent to e - s < INT64_MIN, but without any
- * overflow */
- return INT64_MAX;
- } else if (s < 0 && e > INT64_MAX + s) {
- /* s is negative: equivalent to e - s > INT64_MAX, but without any
- * overflow */
- return INT64_MAX;
- }
-
- return e - s;
-}
-
-/** Return the number of microseconds elapsed between *start and *end.
- * Returns LONG_MAX on overflow and underflow.
- */
-long
-tv_udiff(const struct timeval *start, const struct timeval *end)
-{
- /* Sanity check tv_usec */
- if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
- "start tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(start->tv_usec));
- return LONG_MAX;
- }
-
- if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
- "end tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(end->tv_usec));
- return LONG_MAX;
- }
-
- /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
- */
- int64_t udiff;
- const int64_t secdiff = tv_secdiff_impl(start, end);
-
- /* end->tv_usec - start->tv_usec can be up to 1 second either way */
- if (secdiff > (int64_t)(LONG_MAX/1000000 - 1) ||
- secdiff < (int64_t)(LONG_MIN/1000000 + 1)) {
- log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
- "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
- return LONG_MAX;
- }
-
- /* we'll never get an overflow here, because we check that both usecs are
- * between 0 and TV_USEC_PER_SEC. */
- udiff = secdiff*1000000 + ((int64_t)end->tv_usec - (int64_t)start->tv_usec);
-
- /* Some compilers are smart enough to work out this is a no-op on L64 */
-#if SIZEOF_LONG < 8
- if (udiff > (int64_t)LONG_MAX || udiff < (int64_t)LONG_MIN) {
- return LONG_MAX;
- }
-#endif
-
- return (long)udiff;
-}
-
-/** Return the number of milliseconds elapsed between *start and *end.
- * If the tv_usec difference is 500, rounds away from zero.
- * Returns LONG_MAX on overflow and underflow.
- */
-long
-tv_mdiff(const struct timeval *start, const struct timeval *end)
-{
- /* Sanity check tv_usec */
- if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
- "start tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(start->tv_usec));
- return LONG_MAX;
- }
-
- if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
- "end tv_usec: " I64_FORMAT " microseconds",
- I64_PRINTF_ARG(end->tv_usec));
- return LONG_MAX;
- }
-
- /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
- */
- int64_t mdiff;
- const int64_t secdiff = tv_secdiff_impl(start, end);
-
- /* end->tv_usec - start->tv_usec can be up to 1 second either way, but the
- * mdiff calculation may add another temporary second for rounding.
- * Whether this actually causes overflow depends on the compiler's constant
- * folding and order of operations. */
- if (secdiff > (int64_t)(LONG_MAX/1000 - 2) ||
- secdiff < (int64_t)(LONG_MIN/1000 + 1)) {
- log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
- "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
- return LONG_MAX;
- }
-
- /* Subtract and round */
- mdiff = secdiff*1000 +
- /* We add a million usec here to ensure that the result is positive,
- * so that the round-towards-zero behavior of the division will give
- * the right result for rounding to the nearest msec. Later we subtract
- * 1000 in order to get the correct result.
- * We'll never get an overflow here, because we check that both usecs are
- * between 0 and TV_USEC_PER_SEC. */
- ((int64_t)end->tv_usec - (int64_t)start->tv_usec + 500 + 1000000) / 1000
- - 1000;
-
- /* Some compilers are smart enough to work out this is a no-op on L64 */
-#if SIZEOF_LONG < 8
- if (mdiff > (int64_t)LONG_MAX || mdiff < (int64_t)LONG_MIN) {
- return LONG_MAX;
- }
-#endif
-
- return (long)mdiff;
-}
-
-/**
- * Converts timeval to milliseconds.
- */
-int64_t
-tv_to_msec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000L;
- /* Round ghetto-style */
- conv += ((int64_t)tv->tv_usec+500)/1000L;
- return conv;
-}
-
#ifdef _WIN32
HANDLE
load_windows_system_library(const TCHAR *library_name)
diff --git a/src/common/util.h b/src/common/util.h
index 3068f023a..f174cd366 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -66,9 +66,6 @@ void tor_log_mallinfo(int severity);
/* String manipulation */
/* Time helpers */
-long tv_udiff(const struct timeval *start, const struct timeval *end);
-long tv_mdiff(const struct timeval *start, const struct timeval *end);
-int64_t tv_to_msec(const struct timeval *tv);
/* File helpers */
diff --git a/src/include.am b/src/include.am
index 8345813b7..ba5421e09 100644
--- a/src/include.am
+++ b/src/include.am
@@ -24,6 +24,7 @@ include src/lib/string/include.am
include src/lib/smartlist_core/include.am
include src/lib/testsupport/include.am
include src/lib/thread/include.am
+include src/lib/time/include.am
include src/lib/tls/include.am
include src/lib/trace/include.am
include src/lib/wallclock/include.am
diff --git a/src/lib/time/.may_include b/src/lib/time/.may_include
new file mode 100644
index 000000000..a35e7a34e
--- /dev/null
+++ b/src/lib/time/.may_include
@@ -0,0 +1,8 @@
+orconfig.h
+
+lib/cc/*.h
+lib/err/*.h
+lib/intmath/*.h
+lib/log/*.h
+lib/time/*.h
+lib/wallclock/*.h
diff --git a/src/common/compat_time.c b/src/lib/time/compat_time.c
similarity index 99%
rename from src/common/compat_time.c
rename to src/lib/time/compat_time.c
index 148f2f895..f50ccb5e3 100644
--- a/src/common/compat_time.c
+++ b/src/lib/time/compat_time.c
@@ -10,7 +10,12 @@
**/
#define COMPAT_TIME_PRIVATE
-#include "common/compat.h"
+#include "lib/time/compat_time.h"
+
+#include "lib/err/torerr.h"
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+#include "lib/intmath/muldiv.h"
#ifdef _WIN32
#include <winsock2.h>
@@ -20,6 +25,9 @@
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -34,9 +42,9 @@
#include <mach/mach_time.h>
#endif
-#include "lib/err/torerr.h"
-#include "lib/log/torlog.h"
-#include "common/util.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#ifdef _WIN32
#undef HAVE_CLOCK_GETTIME
diff --git a/src/common/compat_time.h b/src/lib/time/compat_time.h
similarity index 99%
rename from src/common/compat_time.h
rename to src/lib/time/compat_time.h
index 2f7e87a63..4427ce8f9 100644
--- a/src/common/compat_time.h
+++ b/src/lib/time/compat_time.h
@@ -19,6 +19,8 @@
#define TOR_COMPAT_TIME_H
#include "orconfig.h"
+#include "lib/cc/torint.h"
+
#include "lib/wallclock/tor_gettimeofday.h"
#ifdef _WIN32
diff --git a/src/lib/time/include.am b/src/lib/time/include.am
new file mode 100644
index 000000000..a3f93a374
--- /dev/null
+++ b/src/lib/time/include.am
@@ -0,0 +1,19 @@
+
+noinst_LIBRARIES += src/lib/libtor-time.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-time-testing.a
+endif
+
+src_lib_libtor_time_a_SOURCES = \
+ src/lib/time/compat_time.c \
+ src/lib/time/tvdiff.c
+
+src_lib_libtor_time_testing_a_SOURCES = \
+ $(src_lib_libtor_time_a_SOURCES)
+src_lib_libtor_time_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_time_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/time/compat_time.h \
+ src/lib/time/tvdiff.h
diff --git a/src/lib/time/tvdiff.c b/src/lib/time/tvdiff.c
new file mode 100644
index 000000000..11c881234
--- /dev/null
+++ b/src/lib/time/tvdiff.c
@@ -0,0 +1,155 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "lib/time/tvdiff.h"
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/log/torlog.h"
+
+#define TOR_USEC_PER_SEC 1000000
+
+/** Return the difference between start->tv_sec and end->tv_sec.
+ * Returns INT64_MAX on overflow and underflow.
+ */
+static int64_t
+tv_secdiff_impl(const struct timeval *start, const struct timeval *end)
+{
+ const int64_t s = (int64_t)start->tv_sec;
+ const int64_t e = (int64_t)end->tv_sec;
+
+ /* This may not be the most efficient way of implemeting this check,
+ * but it's easy to see that it's correct and doesn't overflow */
+
+ if (s > 0 && e < INT64_MIN + s) {
+ /* s is positive: equivalent to e - s < INT64_MIN, but without any
+ * overflow */
+ return INT64_MAX;
+ } else if (s < 0 && e > INT64_MAX + s) {
+ /* s is negative: equivalent to e - s > INT64_MAX, but without any
+ * overflow */
+ return INT64_MAX;
+ }
+
+ return e - s;
+}
+
+/** Return the number of microseconds elapsed between *start and *end.
+ * Returns LONG_MAX on overflow and underflow.
+ */
+long
+tv_udiff(const struct timeval *start, const struct timeval *end)
+{
+ /* Sanity check tv_usec */
+ if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
+ "start tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(start->tv_usec));
+ return LONG_MAX;
+ }
+
+ if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
+ "end tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(end->tv_usec));
+ return LONG_MAX;
+ }
+
+ /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
+ */
+ int64_t udiff;
+ const int64_t secdiff = tv_secdiff_impl(start, end);
+
+ /* end->tv_usec - start->tv_usec can be up to 1 second either way */
+ if (secdiff > (int64_t)(LONG_MAX/1000000 - 1) ||
+ secdiff < (int64_t)(LONG_MIN/1000000 + 1)) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
+ "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
+ return LONG_MAX;
+ }
+
+ /* we'll never get an overflow here, because we check that both usecs are
+ * between 0 and TV_USEC_PER_SEC. */
+ udiff = secdiff*1000000 + ((int64_t)end->tv_usec - (int64_t)start->tv_usec);
+
+ /* Some compilers are smart enough to work out this is a no-op on L64 */
+#if SIZEOF_LONG < 8
+ if (udiff > (int64_t)LONG_MAX || udiff < (int64_t)LONG_MIN) {
+ return LONG_MAX;
+ }
+#endif
+
+ return (long)udiff;
+}
+
+/** Return the number of milliseconds elapsed between *start and *end.
+ * If the tv_usec difference is 500, rounds away from zero.
+ * Returns LONG_MAX on overflow and underflow.
+ */
+long
+tv_mdiff(const struct timeval *start, const struct timeval *end)
+{
+ /* Sanity check tv_usec */
+ if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
+ "start tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(start->tv_usec));
+ return LONG_MAX;
+ }
+
+ if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
+ "end tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(end->tv_usec));
+ return LONG_MAX;
+ }
+
+ /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
+ */
+ int64_t mdiff;
+ const int64_t secdiff = tv_secdiff_impl(start, end);
+
+ /* end->tv_usec - start->tv_usec can be up to 1 second either way, but the
+ * mdiff calculation may add another temporary second for rounding.
+ * Whether this actually causes overflow depends on the compiler's constant
+ * folding and order of operations. */
+ if (secdiff > (int64_t)(LONG_MAX/1000 - 2) ||
+ secdiff < (int64_t)(LONG_MIN/1000 + 1)) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
+ "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
+ return LONG_MAX;
+ }
+
+ /* Subtract and round */
+ mdiff = secdiff*1000 +
+ /* We add a million usec here to ensure that the result is positive,
+ * so that the round-towards-zero behavior of the division will give
+ * the right result for rounding to the nearest msec. Later we subtract
+ * 1000 in order to get the correct result.
+ * We'll never get an overflow here, because we check that both usecs are
+ * between 0 and TV_USEC_PER_SEC. */
+ ((int64_t)end->tv_usec - (int64_t)start->tv_usec + 500 + 1000000) / 1000
+ - 1000;
+
+ /* Some compilers are smart enough to work out this is a no-op on L64 */
+#if SIZEOF_LONG < 8
+ if (mdiff > (int64_t)LONG_MAX || mdiff < (int64_t)LONG_MIN) {
+ return LONG_MAX;
+ }
+#endif
+
+ return (long)mdiff;
+}
+
+/**
+ * Converts timeval to milliseconds.
+ */
+int64_t
+tv_to_msec(const struct timeval *tv)
+{
+ int64_t conv = ((int64_t)tv->tv_sec)*1000L;
+ /* Round ghetto-style */
+ conv += ((int64_t)tv->tv_usec+500)/1000L;
+ return conv;
+}
diff --git a/src/lib/time/tvdiff.h b/src/lib/time/tvdiff.h
new file mode 100644
index 000000000..215de9cf3
--- /dev/null
+++ b/src/lib/time/tvdiff.h
@@ -0,0 +1,16 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_TVDIFF_H
+#define TOR_TVDIFF_H
+
+#include "lib/cc/torint.h"
+struct timeval;
+
+long tv_udiff(const struct timeval *start, const struct timeval *end);
+long tv_mdiff(const struct timeval *start, const struct timeval *end);
+int64_t tv_to_msec(const struct timeval *tv);
+
+#endif
diff --git a/src/lib/wallclock/include.am b/src/lib/wallclock/include.am
index 7b735e97e..7864c21e1 100644
--- a/src/lib/wallclock/include.am
+++ b/src/lib/wallclock/include.am
@@ -17,5 +17,6 @@ src_lib_libtor_wallclock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
noinst_HEADERS += \
src/lib/wallclock/approx_time.h \
+ src/lib/wallclock/timeval.h \
src/lib/wallclock/tm_cvt.h \
src/lib/wallclock/tor_gettimeofday.h
diff --git a/src/lib/wallclock/timeval.c b/src/lib/wallclock/timeval.c
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/lib/wallclock/timeval.h b/src/lib/wallclock/timeval.h
new file mode 100644
index 000000000..6a9b36a02
--- /dev/null
+++ b/src/lib/wallclock/timeval.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_TIMEVAL_H
+#define TOR_TIMEVAL_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifndef timeradd
+/** Replacement for timeradd on platforms that do not have it: sets tvout to
+ * the sum of tv1 and tv2. */
+#define timeradd(tv1,tv2,tvout) \
+ do { \
+ (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec; \
+ (tvout)->tv_usec = (tv1)->tv_usec + (tv2)->tv_usec; \
+ if ((tvout)->tv_usec >= 1000000) { \
+ (tvout)->tv_usec -= 1000000; \
+ (tvout)->tv_sec++; \
+ } \
+ } while (0)
+#endif /* !defined(timeradd) */
+
+#ifndef timersub
+/** Replacement for timersub on platforms that do not have it: sets tvout to
+ * tv1 minus tv2. */
+#define timersub(tv1,tv2,tvout) \
+ do { \
+ (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec; \
+ (tvout)->tv_usec = (tv1)->tv_usec - (tv2)->tv_usec; \
+ if ((tvout)->tv_usec < 0) { \
+ (tvout)->tv_usec += 1000000; \
+ (tvout)->tv_sec--; \
+ } \
+ } while (0)
+#endif /* !defined(timersub) */
+
+#ifndef timercmp
+/** Replacement for timercmp on platforms that do not have it: returns true
+ * iff the relational operator "op" makes the expression tv1 op tv2 true.
+ *
+ * Note that while this definition should work for all boolean operators, some
+ * platforms' native timercmp definitions do not support >=, <=, or ==. So
+ * don't use those.
+ */
+#define timercmp(tv1,tv2,op) \
+ (((tv1)->tv_sec == (tv2)->tv_sec) ? \
+ ((tv1)->tv_usec op (tv2)->tv_usec) : \
+ ((tv1)->tv_sec op (tv2)->tv_sec))
+#endif /* !defined(timercmp) */
+
+#endif
diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c
index 08186ca9a..c2abb2d14 100644
--- a/src/or/circuitstats.c
+++ b/src/or/circuitstats.c
@@ -41,6 +41,7 @@
#include "or/circuitlist.h"
#include "or/circuituse.h"
#include "lib/math/fp.h"
+#include "lib/time/tvdiff.h"
#include "or/crypt_path_st.h"
#include "or/origin_circuit_st.h"
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 3669eb7f1..71abd5d6c 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -57,6 +57,7 @@
#include "or/router.h"
#include "or/routerlist.h"
#include "lib/math/fp.h"
+#include "lib/time/tvdiff.h"
#include "or/cpath_build_state_st.h"
#include "or/dir_connection_st.h"
diff --git a/src/or/geoip.c b/src/or/geoip.c
index 330477e4c..4a55e3f8d 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -39,6 +39,7 @@
#include "or/routerlist.h"
#include "lib/container/order.h"
+#include "lib/time/tvdiff.h"
static void init_geoip_countries(void);
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 8fe308826..220b05b49 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -31,6 +31,7 @@
#include "lib/thread/numcpus.h"
#include "lib/math/fp.h"
#include "lib/math/laplace.h"
+#include "lib/time/tvdiff.h"
#ifdef HAVE_PWD_H
#include <pwd.h>