tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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) */