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