Line data Source code
1 : /* Copyright (c) 2003-2004, Roger Dingledine
2 : * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 : /* See LICENSE for licensing information */
5 :
6 : /**
7 : * \file compat_time.h
8 : *
9 : * \brief Functions and types for monotonic times.
10 : *
11 : * monotime_* functions try to provide a high-resolution monotonic timer with
12 : * something the best resolution the system provides. monotime_coarse_*
13 : * functions run faster (if the operating system gives us a way to do that)
14 : * but produce a less accurate timer: accuracy will probably be on the order
15 : * of tens of milliseconds.
16 : */
17 :
18 : /* Q: When should I use monotonic time?
19 : *
20 : * A: If you need a time that never decreases, use monotonic time. If you need
21 : * to send a time to a user or another process, or store a time, use the
22 : * wall-clock time.
23 : *
24 : * Q: Should you use monotime or monotime_coarse as your source?
25 : *
26 : * A: Generally, you get better precision with monotime, but better
27 : * performance with monotime_coarse.
28 : *
29 : * Q: What is a "monotonic" time, exactly?
30 : *
31 : * A: Monotonic times are strictly non-decreasing. The difference between any
32 : * previous monotonic time, and the current monotonic time, is always greater
33 : * than *or equal to* zero.
34 : * Zero deltas happen more often:
35 : * - on Windows (due to an OS bug),
36 : * - when using monotime_coarse, or on systems with low-resolution timers,
37 : * - on platforms where we emulate monotonic time using wall-clock time, and
38 : * - when using time units that are larger than nanoseconds (due to
39 : * truncation on division).
40 : *
41 : * Q: Should you use monotime_t or monotime_coarse_t directly? Should you use
42 : * usec? msec? "stamp units?"
43 : *
44 : * A: Using monotime_t and monotime_coarse_t directly is most time-efficient,
45 : * since no conversion needs to happen. But they can potentially use more
46 : * memory than you would need for a usec/msec/"stamp unit" count.
47 : *
48 : * Converting to usec or msec on some platforms, and working with them in
49 : * general, creates a risk of doing a 64-bit division. 64-bit division is
50 : * expensive on 32-bit platforms, which still do exist.
51 : *
52 : * The "stamp unit" type is designed to give a type that is cheap to convert
53 : * from monotime_coarse, has resolution of about 1-2ms, and fits nicely in a
54 : * 32-bit integer. Its downside is that it does not correspond directly
55 : * to a natural unit of time.
56 : *
57 : * There is not much point in using "coarse usec" or "coarse nsec", since the
58 : * current coarse monotime implementations give you on the order of
59 : * milliseconds of precision.
60 : *
61 : * Q: So, what backends is monotime_coarse using?
62 : *
63 : * A: Generally speaking, it uses "whatever monotonic-ish time implementation
64 : * does not require a context switch." The various implementations provide
65 : * this by having a view of the current time in a read-only memory page that
66 : * is updated with a frequency corresponding to the kernel's tick count.
67 : *
68 : * On Windows, monotime_coarse uses GetCount64() [or GetTickCount() on
69 : * obsolete systems]. MSDN claims that the resolution is "typically in the
70 : * range of 10-16 msec", but it has said that for years. Storing
71 : * monotime_coarse_t uses 8 bytes.
72 : *
73 : * On OSX/iOS, monotime_coarse uses uses mach_approximate_time() where
74 : * available, and falls back to regular monotime. The precision is not
75 : * documented, but the implementation is open-source: it reads from a page
76 : * that the kernel updates. Storing monotime_coarse_t uses 8 bytes.
77 : *
78 : * On unixy systems, monotime_coarse uses clock_gettime() with
79 : * CLOCK_MONOTONIC_COARSE where available, and falls back to CLOCK_MONOTONIC.
80 : * It typically uses vdso tricks to read from a page that the kernel updates.
81 : * Its precision fixed, but you can get it with clock_getres(): on my Linux
82 : * desktop, it claims to be 1 msec, but it will depend on the system HZ
83 : * setting. Storing monotime_coarse_t uses 16 bytes.
84 : *
85 : * [TODO: Try CLOCK_MONOTONIC_FAST on foobsd.]
86 : *
87 : * Q: What backends is regular monotonic time using?
88 : *
89 : * A: In general, regular monotime uses something that requires a system call.
90 : * On platforms where system calls are cheap, you win! Otherwise, you lose.
91 : *
92 : * On Windows, monotonic time uses QuereyPerformanceCounter. Storing
93 : * monotime_t costs 8 bytes.
94 : *
95 : * On OSX/Apple, monotonic time uses mach_absolute_time. Storing
96 : * monotime_t costs 8 bytes.
97 : *
98 : * On unixy systems, monotonic time uses CLOCK_MONOTONIC. Storing
99 : * monotime_t costs 16 bytes.
100 : *
101 : * Q: Tell me about the costs of converting to a 64-bit nsec, usec, or msec
102 : * count.
103 : *
104 : * A: Windows, coarse: Cheap, since it's all multiplication.
105 : *
106 : * Windows, precise: Expensive on 32-bit: it needs 64-bit division.
107 : *
108 : * Apple, all: Expensive on 32-bit: it needs 64-bit division.
109 : *
110 : * Unixy, all: Fairly cheap, since the only division required is dividing
111 : * tv_nsec 1000, and nanoseconds-per-second fits in a 32-bit value.
112 : *
113 : * All, "timestamp units": Cheap everywhere: it never divides.
114 : *
115 : * Q: This is only somewhat related, but how much precision could I hope for
116 : * from a libevent time?
117 : *
118 : * A: Actually, it's _very_ related if you're timing in order to have a
119 : * timeout happen.
120 : *
121 : * On Windows, it uses select: you could in theory have a microsecond
122 : * resolution, but it usually isn't that accurate.
123 : *
124 : * On OSX, iOS, and BSD, you have kqueue: You could in theory have a nanosecond
125 : * resolution, but it usually isn't that accurate.
126 : *
127 : * On Linux, you have epoll: It has a millisecond resolution. Some recent
128 : * Libevents can also use timerfd for higher resolution if
129 : * EVENT_BASE_FLAG_PRECISE_TIMER is set: Tor doesn't set that flag.
130 : */
131 :
132 : #ifndef TOR_COMPAT_TIME_H
133 : #define TOR_COMPAT_TIME_H
134 :
135 : #include "orconfig.h"
136 : #include "lib/cc/torint.h"
137 :
138 : #include "lib/wallclock/tor_gettimeofday.h"
139 :
140 : #ifdef _WIN32
141 : #undef HAVE_CLOCK_GETTIME
142 : #endif
143 :
144 : #if defined(HAVE_CLOCK_GETTIME)
145 : /* to ensure definition of CLOCK_MONOTONIC_COARSE if it's there */
146 : #include <time.h>
147 : #endif
148 :
149 : #if !defined(HAVE_STRUCT_TIMEVAL_TV_SEC)
150 : /** Implementation of timeval for platforms that don't have it. */
151 : struct timeval {
152 : time_t tv_sec;
153 : unsigned int tv_usec;
154 : };
155 : #endif /* !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) */
156 :
157 : /** Represents a monotonic timer in a platform-dependent way. */
158 : typedef struct monotime_t {
159 : #ifdef __APPLE__
160 : /* On apple, there is a 64-bit counter whose precision we must look up. */
161 : uint64_t abstime_;
162 : #elif defined(HAVE_CLOCK_GETTIME)
163 : /* It sure would be nice to use clock_gettime(). Posix is a nice thing. */
164 : struct timespec ts_;
165 : #elif defined (_WIN32)
166 : /* On Windows, there is a 64-bit counter whose precision we must look up. */
167 : int64_t pcount_;
168 : #else
169 : #define MONOTIME_USING_GETTIMEOFDAY
170 : /* Otherwise, we will be stuck using gettimeofday. */
171 : struct timeval tv_;
172 : #endif /* defined(__APPLE__) || ... */
173 : } monotime_t;
174 :
175 : #if defined(CLOCK_MONOTONIC_COARSE) && \
176 : defined(HAVE_CLOCK_GETTIME)
177 : #define MONOTIME_COARSE_FN_IS_DIFFERENT
178 : #define monotime_coarse_t monotime_t
179 : #elif defined(_WIN32)
180 : #define MONOTIME_COARSE_FN_IS_DIFFERENT
181 : #define MONOTIME_COARSE_TYPE_IS_DIFFERENT
182 : /** Represents a coarse monotonic time in a platform-independent way. */
183 : typedef struct monotime_coarse_t {
184 : uint64_t tick_count_;
185 : } monotime_coarse_t;
186 : #elif defined(__APPLE__) && defined(HAVE_MACH_APPROXIMATE_TIME)
187 : #define MONOTIME_COARSE_FN_IS_DIFFERENT
188 : #define monotime_coarse_t monotime_t
189 : #else
190 : #define monotime_coarse_t monotime_t
191 : #endif /* defined(CLOCK_MONOTONIC_COARSE) && ... || ... */
192 :
193 : /**
194 : * Initialize the timing subsystem. This function is idempotent.
195 : */
196 : void monotime_init(void);
197 : /**
198 : * Set <b>out</b> to the current time.
199 : */
200 : void monotime_get(monotime_t *out);
201 : /**
202 : * Return the number of nanoseconds between <b>start</b> and <b>end</b>.
203 : * The returned value may be equal to zero.
204 : */
205 : int64_t monotime_diff_nsec(const monotime_t *start, const monotime_t *end);
206 : /**
207 : * Return the number of microseconds between <b>start</b> and <b>end</b>.
208 : * The returned value may be equal to zero.
209 : * Fractional units are truncated, not rounded.
210 : */
211 : int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end);
212 : /**
213 : * Return the number of milliseconds between <b>start</b> and <b>end</b>.
214 : * The returned value may be equal to zero.
215 : * Fractional units are truncated, not rounded.
216 : */
217 : int64_t monotime_diff_msec(const monotime_t *start, const monotime_t *end);
218 : /**
219 : * Return the number of nanoseconds since the timer system was initialized.
220 : * The returned value may be equal to zero.
221 : */
222 : uint64_t monotime_absolute_nsec(void);
223 : /**
224 : * Return the number of microseconds since the timer system was initialized.
225 : * The returned value may be equal to zero.
226 : * Fractional units are truncated, not rounded.
227 : */
228 : MOCK_DECL(uint64_t, monotime_absolute_usec,(void));
229 : /**
230 : * Return the number of milliseconds since the timer system was initialized.
231 : * The returned value may be equal to zero.
232 : * Fractional units are truncated, not rounded.
233 : */
234 : uint64_t monotime_absolute_msec(void);
235 :
236 : /**
237 : * Set <b>out</b> to zero.
238 : */
239 : void monotime_zero(monotime_t *out);
240 : /**
241 : * Return true iff <b>out</b> is zero
242 : */
243 : int monotime_is_zero(const monotime_t *out);
244 :
245 : /**
246 : * Set <b>out</b> to N milliseconds after <b>val</b>.
247 : */
248 : /* XXXX We should add a more generic function here if we ever need to */
249 : void monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec);
250 :
251 : #if defined(MONOTIME_COARSE_FN_IS_DIFFERENT)
252 : /**
253 : * Set <b>out</b> to the current coarse time.
254 : */
255 : void monotime_coarse_get(monotime_coarse_t *out);
256 : /**
257 : * Like monotime_absolute_*(), but faster on some platforms.
258 : */
259 : uint64_t monotime_coarse_absolute_nsec(void);
260 : uint64_t monotime_coarse_absolute_usec(void);
261 : uint64_t monotime_coarse_absolute_msec(void);
262 : #else /* !defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */
263 : #define monotime_coarse_get monotime_get
264 : #define monotime_coarse_absolute_nsec monotime_absolute_nsec
265 : #define monotime_coarse_absolute_usec monotime_absolute_usec
266 : #define monotime_coarse_absolute_msec monotime_absolute_msec
267 : #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */
268 :
269 : /**
270 : * Return a "timestamp" approximation for a coarse monotonic timer.
271 : * This timestamp is meant to be fast to calculate and easy to
272 : * compare, and have a unit of something roughly around 1 msec.
273 : *
274 : * It will wrap over from time to time.
275 : *
276 : * It has no defined zero point.
277 : */
278 : uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t);
279 : /**
280 : * Convert a difference, expressed in the units of monotime_coarse_to_stamp,
281 : * into an approximate number of milliseconds.
282 : *
283 : * The returned value may be equal to zero.
284 : * Fractional units are truncated, not rounded.
285 : */
286 : uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units);
287 : uint64_t monotime_msec_to_approx_coarse_stamp_units(uint64_t msec);
288 : uint32_t monotime_coarse_get_stamp(void);
289 :
290 : #if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT)
291 : /**
292 : * Like monotime_diff_*(), but faster on some platforms.
293 : */
294 : int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start,
295 : const monotime_coarse_t *end);
296 : int64_t monotime_coarse_diff_usec(const monotime_coarse_t *start,
297 : const monotime_coarse_t *end);
298 : int64_t monotime_coarse_diff_msec(const monotime_coarse_t *start,
299 : const monotime_coarse_t *end);
300 : /**
301 : * Like monotime_*(), but faster on some platforms.
302 : */
303 : void monotime_coarse_zero(monotime_coarse_t *out);
304 : int monotime_coarse_is_zero(const monotime_coarse_t *val);
305 : void monotime_coarse_add_msec(monotime_coarse_t *out,
306 : const monotime_coarse_t *val, uint32_t msec);
307 : #else /* !defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */
308 : #define monotime_coarse_diff_nsec monotime_diff_nsec
309 : #define monotime_coarse_diff_usec monotime_diff_usec
310 : #define monotime_coarse_diff_msec monotime_diff_msec
311 : #define monotime_coarse_zero monotime_zero
312 : #define monotime_coarse_is_zero monotime_is_zero
313 : #define monotime_coarse_add_msec monotime_add_msec
314 : #endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */
315 :
316 : /**
317 : * As monotime_coarse_diff_msec, but avoid 64-bit division.
318 : *
319 : * Requires that the difference fit into an int32_t; not for use with
320 : * large time differences.
321 : *
322 : * The returned value may be equal to zero.
323 : * Fractional units are truncated, not rounded.
324 : */
325 : int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
326 : const monotime_coarse_t *end);
327 :
328 : /**
329 : * As monotime_coarse_diff_msec, but avoid 64-bit division if it is expensive.
330 : *
331 : * Requires that the difference fit into an int32_t; not for use with
332 : * large time differences.
333 : *
334 : * The returned value may be equal to zero.
335 : * Fractional units are truncated, not rounded.
336 : */
337 : static inline int32_t
338 224 : monotime_coarse_diff_msec32(const monotime_coarse_t *start,
339 : const monotime_coarse_t *end)
340 : {
341 : #if SIZEOF_VOID_P == 8
342 : // on a 64-bit platform, let's assume 64/64 division is cheap.
343 224 : return (int32_t) monotime_coarse_diff_msec(start, end);
344 : #else
345 : #define USING_32BIT_MSEC_HACK
346 : return monotime_coarse_diff_msec32_(start, end);
347 : #endif /* SIZEOF_VOID_P == 8 */
348 : }
349 :
350 : #ifdef TOR_UNIT_TESTS
351 : void tor_sleep_msec(int msec);
352 :
353 : void monotime_enable_test_mocking(void);
354 : void monotime_disable_test_mocking(void);
355 : void monotime_set_mock_time_nsec(int64_t);
356 : #if defined(MONOTIME_COARSE_FN_IS_DIFFERENT)
357 : void monotime_coarse_set_mock_time_nsec(int64_t);
358 : #else
359 : #define monotime_coarse_set_mock_time_nsec monotime_set_mock_time_nsec
360 : #endif
361 : #endif /* defined(TOR_UNIT_TESTS) */
362 :
363 : #ifdef COMPAT_TIME_PRIVATE
364 : #if defined(_WIN32) || defined(TOR_UNIT_TESTS)
365 : STATIC int64_t ratchet_performance_counter(int64_t count_raw);
366 : STATIC int64_t ratchet_coarse_performance_counter(int64_t count_raw);
367 : #endif
368 : #if defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS)
369 : STATIC void ratchet_timeval(const struct timeval *timeval_raw,
370 : struct timeval *out);
371 : #endif
372 : #ifdef TOR_UNIT_TESTS
373 : void monotime_reset_ratchets_for_testing(void);
374 : #endif
375 : #endif /* defined(COMPAT_TIME_PRIVATE) */
376 :
377 : #endif /* !defined(TOR_COMPAT_TIME_H) */
|