aboutsummaryrefslogtreecommitdiff
path: root/src/lib/wallclock
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-06-21 17:33:49 -0400
committerNick Mathewson <nickm@torproject.org>2018-06-22 09:49:13 -0400
commit9426751b72e922b5ee2b00bcc6158f5651a81014 (patch)
tree08b063dca1b75c7239ed62554b0cc851ea6b026e /src/lib/wallclock
parentd1cada5a8a7e1631e25f5f413c66d5c9e5113e7a (diff)
downloadtor-9426751b72e922b5ee2b00bcc6158f5651a81014.tar.gz
tor-9426751b72e922b5ee2b00bcc6158f5651a81014.zip
Extract our code for answering "what time is it right now".
The other time stuff is higher-level
Diffstat (limited to 'src/lib/wallclock')
-rw-r--r--src/lib/wallclock/.may_include4
-rw-r--r--src/lib/wallclock/approx_time.c38
-rw-r--r--src/lib/wallclock/approx_time.h20
-rw-r--r--src/lib/wallclock/include.am19
-rw-r--r--src/lib/wallclock/tor_gettimeofday.c82
-rw-r--r--src/lib/wallclock/tor_gettimeofday.h15
6 files changed, 178 insertions, 0 deletions
diff --git a/src/lib/wallclock/.may_include b/src/lib/wallclock/.may_include
new file mode 100644
index 0000000000..686d9196fd
--- /dev/null
+++ b/src/lib/wallclock/.may_include
@@ -0,0 +1,4 @@
+orconfig.h
+lib/err/*.h
+lib/wallclock/*.h
+lib/testsupport/*.h
diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c
new file mode 100644
index 0000000000..2528954f13
--- /dev/null
+++ b/src/lib/wallclock/approx_time.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/wallclock/approx_time.h"
+
+/* =====
+ * Cached time
+ * ===== */
+
+#ifndef TIME_IS_FAST
+/** Cached estimate of the current time. Updated around once per second;
+ * may be a few seconds off if we are really busy. This is a hack to avoid
+ * calling time(NULL) (which not everybody has optimized) on critical paths.
+ */
+static time_t cached_approx_time = 0;
+
+/** Return a cached estimate of the current time from when
+ * update_approx_time() was last called. This is a hack to avoid calling
+ * time(NULL) on critical paths: please do not even think of calling it
+ * anywhere else. */
+time_t
+approx_time(void)
+{
+ return cached_approx_time;
+}
+
+/** Update the cached estimate of the current time. This function SHOULD be
+ * called once per second, and MUST be called before the first call to
+ * get_approx_time. */
+void
+update_approx_time(time_t now)
+{
+ cached_approx_time = now;
+}
+#endif /* !defined(TIME_IS_FAST) */
diff --git a/src/lib/wallclock/approx_time.h b/src/lib/wallclock/approx_time.h
new file mode 100644
index 0000000000..c57ff5bcd3
--- /dev/null
+++ b/src/lib/wallclock/approx_time.h
@@ -0,0 +1,20 @@
+/* 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_APPROX_TIME_H
+#define TOR_APPROX_TIME_H
+
+#include <time.h>
+
+/* Cached time */
+#ifdef TIME_IS_FAST
+#define approx_time() time(NULL)
+#define update_approx_time(t) STMT_NIL
+#else
+time_t approx_time(void);
+void update_approx_time(time_t now);
+#endif /* defined(TIME_IS_FAST) */
+
+#endif
diff --git a/src/lib/wallclock/include.am b/src/lib/wallclock/include.am
new file mode 100644
index 0000000000..d414eb4688
--- /dev/null
+++ b/src/lib/wallclock/include.am
@@ -0,0 +1,19 @@
+
+noinst_LIBRARIES += src/lib/libtor-wallclock.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-wallclock-testing.a
+endif
+
+src_lib_libtor_wallclock_a_SOURCES = \
+ src/lib/wallclock/approx_time.c \
+ src/lib/wallclock/tor_gettimeofday.c
+
+src_lib_libtor_wallclock_testing_a_SOURCES = \
+ $(src_lib_libtor_wallclock_a_SOURCES)
+src_lib_libtor_wallclock_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_wallclock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS += \
+ src/lib/wallclock/approx_time.h \
+ src/lib/wallclock/tor_gettimeofday.h
diff --git a/src/lib/wallclock/tor_gettimeofday.c b/src/lib/wallclock/tor_gettimeofday.c
new file mode 100644
index 0000000000..83081d9c98
--- /dev/null
+++ b/src/lib/wallclock/tor_gettimeofday.c
@@ -0,0 +1,82 @@
+/* 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 */
+
+/**
+ * \file compat_time.c
+ * \brief Portable wrappers for finding out the current time, running
+ * timers, etc.
+ **/
+
+#include "orconfig.h"
+#include "lib/err/torerr.h"
+#include "lib/wallclock/tor_gettimeofday.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_FTIME
+#include <sys/timeb.h>
+#endif
+#endif
+
+/** Set *timeval to the current time of day. On error, log and terminate.
+ * (Same as gettimeofday(timeval,NULL), but never returns -1.)
+ */
+MOCK_IMPL(void,
+tor_gettimeofday, (struct timeval *timeval))
+{
+#ifdef _WIN32
+ /* Epoch bias copied from perl: number of units between windows epoch and
+ * Unix epoch. */
+#define EPOCH_BIAS U64_LITERAL(116444736000000000)
+#define UNITS_PER_SEC U64_LITERAL(10000000)
+#define USEC_PER_SEC U64_LITERAL(1000000)
+#define UNITS_PER_USEC U64_LITERAL(10)
+ union {
+ uint64_t ft_64;
+ FILETIME ft_ft;
+ } ft;
+ /* number of 100-nsec units since Jan 1, 1601 */
+ GetSystemTimeAsFileTime(&ft.ft_ft);
+ if (ft.ft_64 < EPOCH_BIAS) {
+ /* LCOV_EXCL_START */
+ log_err(LD_GENERAL,"System time is before 1970; failing.");
+ exit(1); // exit ok: system clock is broken.
+ /* LCOV_EXCL_STOP */
+ }
+ ft.ft_64 -= EPOCH_BIAS;
+ timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
+ timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
+#elif defined(HAVE_GETTIMEOFDAY)
+ if (gettimeofday(timeval, NULL)) {
+ /* LCOV_EXCL_START */
+ /* If gettimeofday dies, we have either given a bad timezone (we didn't),
+ or segfaulted.*/
+ raw_assert_unreached_msg("gettimeofday failed");
+ /* LCOV_EXCL_STOP */
+ }
+#elif defined(HAVE_FTIME)
+ struct timeb tb;
+ ftime(&tb);
+ timeval->tv_sec = tb.time;
+ timeval->tv_usec = tb.millitm * 1000;
+#else
+#error "No way to get time."
+#endif /* defined(_WIN32) || ... */
+ return;
+}
diff --git a/src/lib/wallclock/tor_gettimeofday.h b/src/lib/wallclock/tor_gettimeofday.h
new file mode 100644
index 0000000000..728ad9565d
--- /dev/null
+++ b/src/lib/wallclock/tor_gettimeofday.h
@@ -0,0 +1,15 @@
+/* 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_GETTIMEOFDAY_H
+#define TOR_GETTIMEOFDAY_H
+
+#include "lib/testsupport/testsupport.h"
+
+struct timeval;
+
+MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval));
+
+#endif