compat_time.h (14696B)
1 /* Copyright (c) 2003-2004, Roger Dingledine 2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 3 * Copyright (c) 2007-2025, 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 * XXX: This hasn't been true for a long time. Expect both coarse and fine 93 * monotime won't require a syscall, but they will have different 94 * costs in terms of low-level synchronization inside the vDSO and 95 * the hardware. The basic guidelines here still apply, but we aren't 96 * really worrying about system calls any more, and the integer div 97 * concerns are becoming nearly unimportant as well. 98 * 99 * On Windows, monotonic time uses QuereyPerformanceCounter. Storing 100 * monotime_t costs 8 bytes. 101 * 102 * On OSX/Apple, monotonic time uses mach_absolute_time. Storing 103 * monotime_t costs 8 bytes. 104 * 105 * On unixy systems, monotonic time uses CLOCK_MONOTONIC. Storing 106 * monotime_t costs 16 bytes. 107 * 108 * Q: Tell me about the costs of converting to a 64-bit nsec, usec, or msec 109 * count. 110 * 111 * A: Windows, coarse: Cheap, since it's all multiplication. 112 * 113 * Windows, precise: Expensive on 32-bit: it needs 64-bit division. 114 * 115 * Apple, all: Expensive on 32-bit: it needs 64-bit division. 116 * 117 * Unixy, all: Fairly cheap, since the only division required is dividing 118 * tv_nsec 1000, and nanoseconds-per-second fits in a 32-bit value. 119 * 120 * All, "timestamp units": Cheap everywhere: it never divides. 121 * 122 * Q: This is only somewhat related, but how much precision could I hope for 123 * from a libevent time? 124 * 125 * A: Actually, it's _very_ related if you're timing in order to have a 126 * timeout happen. 127 * 128 * On Windows, it uses select: you could in theory have a microsecond 129 * resolution, but it usually isn't that accurate. 130 * 131 * On OSX, iOS, and BSD, you have kqueue: You could in theory have a nanosecond 132 * resolution, but it usually isn't that accurate. 133 * 134 * On Linux, you have epoll: It has a millisecond resolution. Some recent 135 * Libevents can also use timerfd for higher resolution if 136 * EVENT_BASE_FLAG_PRECISE_TIMER is set: Tor doesn't set that flag. 137 */ 138 139 #ifndef TOR_COMPAT_TIME_H 140 #define TOR_COMPAT_TIME_H 141 142 #include "orconfig.h" 143 #include "lib/cc/torint.h" 144 145 #include "lib/wallclock/tor_gettimeofday.h" 146 147 #ifdef _WIN32 148 #undef HAVE_CLOCK_GETTIME 149 #endif 150 151 #if defined(HAVE_CLOCK_GETTIME) 152 /* to ensure definition of CLOCK_MONOTONIC_COARSE if it's there */ 153 #include <time.h> 154 #endif 155 156 #if !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) 157 /** Implementation of timeval for platforms that don't have it. */ 158 struct timeval { 159 time_t tv_sec; 160 unsigned int tv_usec; 161 }; 162 #endif /* !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) */ 163 164 /** Represents a monotonic timer in a platform-dependent way. */ 165 typedef struct monotime_t { 166 #ifdef __APPLE__ 167 /* On apple, there is a 64-bit counter whose precision we must look up. */ 168 uint64_t abstime_; 169 #elif defined(HAVE_CLOCK_GETTIME) 170 /* It sure would be nice to use clock_gettime(). Posix is a nice thing. */ 171 struct timespec ts_; 172 #elif defined (_WIN32) 173 /* On Windows, there is a 64-bit counter whose precision we must look up. */ 174 int64_t pcount_; 175 #else 176 #define MONOTIME_USING_GETTIMEOFDAY 177 /* Otherwise, we will be stuck using gettimeofday. */ 178 struct timeval tv_; 179 #endif /* defined(__APPLE__) || ... */ 180 } monotime_t; 181 182 #if defined(CLOCK_MONOTONIC_COARSE) && \ 183 defined(HAVE_CLOCK_GETTIME) 184 #define MONOTIME_COARSE_FN_IS_DIFFERENT 185 #define monotime_coarse_t monotime_t 186 #elif defined(_WIN32) 187 #define MONOTIME_COARSE_FN_IS_DIFFERENT 188 #define MONOTIME_COARSE_TYPE_IS_DIFFERENT 189 /** Represents a coarse monotonic time in a platform-independent way. */ 190 typedef struct monotime_coarse_t { 191 uint64_t tick_count_; 192 } monotime_coarse_t; 193 #elif defined(__APPLE__) && defined(HAVE_MACH_APPROXIMATE_TIME) 194 #define MONOTIME_COARSE_FN_IS_DIFFERENT 195 #define monotime_coarse_t monotime_t 196 #else 197 #define monotime_coarse_t monotime_t 198 #endif /* defined(CLOCK_MONOTONIC_COARSE) && ... || ... */ 199 200 /** 201 * Initialize the timing subsystem. This function is idempotent. 202 */ 203 void monotime_init(void); 204 /** 205 * Set <b>out</b> to the current time. 206 */ 207 void monotime_get(monotime_t *out); 208 /** 209 * Return the number of nanoseconds between <b>start</b> and <b>end</b>. 210 * The returned value may be equal to zero. 211 */ 212 int64_t monotime_diff_nsec(const monotime_t *start, const monotime_t *end); 213 /** 214 * Return the number of microseconds between <b>start</b> and <b>end</b>. 215 * The returned value may be equal to zero. 216 * Fractional units are truncated, not rounded. 217 */ 218 int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end); 219 /** 220 * Return the number of milliseconds between <b>start</b> and <b>end</b>. 221 * The returned value may be equal to zero. 222 * Fractional units are truncated, not rounded. 223 */ 224 int64_t monotime_diff_msec(const monotime_t *start, const monotime_t *end); 225 /** 226 * Return the number of nanoseconds since the timer system was initialized. 227 * The returned value may be equal to zero. 228 */ 229 uint64_t monotime_absolute_nsec(void); 230 /** 231 * Return the number of microseconds since the timer system was initialized. 232 * The returned value may be equal to zero. 233 * Fractional units are truncated, not rounded. 234 */ 235 MOCK_DECL(uint64_t, monotime_absolute_usec,(void)); 236 /** 237 * Return the number of milliseconds since the timer system was initialized. 238 * The returned value may be equal to zero. 239 * Fractional units are truncated, not rounded. 240 */ 241 uint64_t monotime_absolute_msec(void); 242 /** 243 * Return the number of seconds since the timer system was initialized. 244 * The returned value may be equal to zero. 245 * Fractional units are truncated, not rounded. 246 */ 247 uint64_t monotime_absolute_sec(void); 248 /** 249 * Set <b>out</b> to zero. 250 */ 251 void monotime_zero(monotime_t *out); 252 /** 253 * Return true iff <b>out</b> is zero 254 */ 255 int monotime_is_zero(const monotime_t *out); 256 257 /** 258 * Set <b>out</b> to N milliseconds after <b>val</b>. 259 */ 260 /* XXXX We should add a more generic function here if we ever need to */ 261 void monotime_add_msec(monotime_t *out, const monotime_t *val, uint32_t msec); 262 263 #if defined(MONOTIME_COARSE_FN_IS_DIFFERENT) 264 /** 265 * Set <b>out</b> to the current coarse time. 266 */ 267 void monotime_coarse_get(monotime_coarse_t *out); 268 /** 269 * Like monotime_absolute_*(), but faster on some platforms. 270 */ 271 uint64_t monotime_coarse_absolute_nsec(void); 272 uint64_t monotime_coarse_absolute_usec(void); 273 uint64_t monotime_coarse_absolute_msec(void); 274 uint64_t monotime_coarse_absolute_sec(void); 275 #else /* !defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ 276 #define monotime_coarse_get monotime_get 277 #define monotime_coarse_absolute_nsec monotime_absolute_nsec 278 #define monotime_coarse_absolute_usec monotime_absolute_usec 279 #define monotime_coarse_absolute_msec monotime_absolute_msec 280 #define monotime_coarse_absolute_sec monotime_absolute_sec 281 #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ 282 283 /** 284 * Return a "timestamp" approximation for a coarse monotonic timer. 285 * This timestamp is meant to be fast to calculate and easy to 286 * compare, and have a unit of something roughly around 1 msec. 287 * 288 * It will wrap over from time to time. 289 * 290 * It has no defined zero point. 291 */ 292 uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t); 293 /** 294 * Convert a difference, expressed in the units of monotime_coarse_to_stamp, 295 * into an approximate number of milliseconds. 296 * 297 * The returned value may be equal to zero. 298 * Fractional units are truncated, not rounded. 299 */ 300 uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units); 301 uint64_t monotime_msec_to_approx_coarse_stamp_units(uint64_t msec); 302 uint32_t monotime_coarse_get_stamp(void); 303 304 #if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) 305 /** 306 * Like monotime_diff_*(), but faster on some platforms. 307 */ 308 int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start, 309 const monotime_coarse_t *end); 310 int64_t monotime_coarse_diff_usec(const monotime_coarse_t *start, 311 const monotime_coarse_t *end); 312 int64_t monotime_coarse_diff_msec(const monotime_coarse_t *start, 313 const monotime_coarse_t *end); 314 /** 315 * Like monotime_*(), but faster on some platforms. 316 */ 317 void monotime_coarse_zero(monotime_coarse_t *out); 318 int monotime_coarse_is_zero(const monotime_coarse_t *val); 319 void monotime_coarse_add_msec(monotime_coarse_t *out, 320 const monotime_coarse_t *val, uint32_t msec); 321 #else /* !defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */ 322 #define monotime_coarse_diff_nsec monotime_diff_nsec 323 #define monotime_coarse_diff_usec monotime_diff_usec 324 #define monotime_coarse_diff_msec monotime_diff_msec 325 #define monotime_coarse_zero monotime_zero 326 #define monotime_coarse_is_zero monotime_is_zero 327 #define monotime_coarse_add_msec monotime_add_msec 328 #endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */ 329 330 /** 331 * As monotime_coarse_diff_msec, but avoid 64-bit division. 332 * 333 * Requires that the difference fit into an int32_t; not for use with 334 * large time differences. 335 * 336 * The returned value may be equal to zero. 337 * Fractional units are truncated, not rounded. 338 */ 339 int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start, 340 const monotime_coarse_t *end); 341 342 /** 343 * As monotime_coarse_diff_msec, but avoid 64-bit division if it is expensive. 344 * 345 * Requires that the difference fit into an int32_t; not for use with 346 * large time differences. 347 * 348 * The returned value may be equal to zero. 349 * Fractional units are truncated, not rounded. 350 */ 351 static inline int32_t 352 monotime_coarse_diff_msec32(const monotime_coarse_t *start, 353 const monotime_coarse_t *end) 354 { 355 #if SIZEOF_VOID_P == 8 356 // on a 64-bit platform, let's assume 64/64 division is cheap. 357 return (int32_t) monotime_coarse_diff_msec(start, end); 358 #else 359 #define USING_32BIT_MSEC_HACK 360 return monotime_coarse_diff_msec32_(start, end); 361 #endif /* SIZEOF_VOID_P == 8 */ 362 } 363 364 void tor_sleep_msec(int msec); 365 366 #ifdef TOR_UNIT_TESTS 367 void monotime_enable_test_mocking(void); 368 void monotime_disable_test_mocking(void); 369 void monotime_set_mock_time_nsec(int64_t); 370 #if defined(MONOTIME_COARSE_FN_IS_DIFFERENT) 371 void monotime_coarse_set_mock_time_nsec(int64_t); 372 #else 373 #define monotime_coarse_set_mock_time_nsec monotime_set_mock_time_nsec 374 #endif 375 #endif /* defined(TOR_UNIT_TESTS) */ 376 377 #ifdef COMPAT_TIME_PRIVATE 378 #if defined(_WIN32) || defined(TOR_UNIT_TESTS) 379 STATIC int64_t ratchet_performance_counter(int64_t count_raw); 380 STATIC int64_t ratchet_coarse_performance_counter(int64_t count_raw); 381 #endif 382 #if defined(MONOTIME_USING_GETTIMEOFDAY) || defined(TOR_UNIT_TESTS) 383 STATIC void ratchet_timeval(const struct timeval *timeval_raw, 384 struct timeval *out); 385 #endif 386 #ifdef TOR_UNIT_TESTS 387 void monotime_reset_ratchets_for_testing(void); 388 #endif 389 #endif /* defined(COMPAT_TIME_PRIVATE) */ 390 391 #endif /* !defined(TOR_COMPAT_TIME_H) */