[tor-commits] [tor/master] Add a new notion of "stamps" to be a fast 32-bit monotonic timestamp

nickm at torproject.org nickm at torproject.org
Wed Dec 6 20:44:32 UTC 2017


commit c3c0a05f51eff73e624b18f651339ed08a122e3d
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Nov 21 12:28:16 2017 -0500

    Add a new notion of "stamps" to be a fast 32-bit monotonic timestamp
    
    The goal here is to replace our use of msec-based timestamps with
    something less precise, but easier to calculate.  We're doing this
    because calculating lots of msec-based timestamps requires lots of
    64/32 division operations, which can be inefficient on 32-bit
    platforms.
    
    We make sure that these stamps can be calculated using only the
    coarse monotonic timer and 32-bit bitwise operations.
---
 src/common/buffers.c     |  6 ++--
 src/common/buffers.h     |  3 +-
 src/common/compat_time.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/compat_time.h | 17 +++++++++++
 src/or/circuitlist.c     | 57 ++++++++++++++++++------------------
 src/or/or.h              |  4 +--
 src/or/relay.c           |  9 +++---
 src/test/test_buffers.c  | 24 ++++++++-------
 src/test/test_oom.c      | 33 +++++++++++----------
 src/test/test_util.c     |  8 +++++
 10 files changed, 171 insertions(+), 66 deletions(-)

diff --git a/src/common/buffers.c b/src/common/buffers.c
index c45e13d55..e0ef0dc77 100644
--- a/src/common/buffers.c
+++ b/src/common/buffers.c
@@ -472,7 +472,7 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
     chunk = chunk_new_with_alloc_size(buf_preferred_chunk_size(capacity));
   }
 
-  chunk->inserted_time = (uint32_t)monotime_coarse_absolute_msec();
+  chunk->inserted_time = monotime_coarse_get_stamp();
 
   if (buf->tail) {
     tor_assert(buf->head);
@@ -487,8 +487,8 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
 }
 
 /** Return the age of the oldest chunk in the buffer <b>buf</b>, in
- * milliseconds.  Requires the current monotonic time, in truncated msec,
- * as its input <b>now</b>.
+ * timestamp units.  Requires the current monotonic timestamp as its
+ * input <b>now</b>.
  */
 uint32_t
 buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now)
diff --git a/src/common/buffers.h b/src/common/buffers.h
index 1eaa5f2d0..fe392d268 100644
--- a/src/common/buffers.h
+++ b/src/common/buffers.h
@@ -79,8 +79,7 @@ typedef struct chunk_t {
   size_t DBG_alloc;
 #endif
   char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */
-  uint32_t inserted_time; /**< Timestamp in truncated ms since epoch
-                           * when this chunk was inserted. */
+  uint32_t inserted_time; /**< Timestamp when this chunk was inserted. */
   char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in
                 * this chunk. */
 } chunk_t;
diff --git a/src/common/compat_time.c b/src/common/compat_time.c
index 1ce6f5ce4..fe0209c8f 100644
--- a/src/common/compat_time.c
+++ b/src/common/compat_time.c
@@ -279,6 +279,7 @@ monotime_reset_ratchets_for_testing(void)
  * nanoseconds.
  */
 static struct mach_timebase_info mach_time_info;
+static int monotime_shift = 0;
 
 static void
 monotime_init_internal(void)
@@ -287,6 +288,14 @@ monotime_init_internal(void)
   int r = mach_timebase_info(&mach_time_info);
   tor_assert(r == 0);
   tor_assert(mach_time_info.denom != 0);
+
+  {
+    // approximate only.
+    uint64_t ns_per_tick = mach_time_info.numer / mach_time_info.denom;
+    uint64_t ms_per_tick = ns_per_tick * ONE_MILLION;
+    // requires that tor_log2(0) == 0.
+    monotime_shift = tor_log2(ms_per_tick);
+  }
 }
 
 /**
@@ -321,6 +330,12 @@ monotime_diff_nsec(const monotime_t *start,
   return diff_nsec;
 }
 
+uint32_t
+monotime_coarse_to_stamp(const monotime_coarse_t *t)
+{
+  return (uint32_t)(t->abstime_ >> monotime_shift);
+}
+
 /* end of "__APPLE__" */
 #elif defined(HAVE_CLOCK_GETTIME)
 
@@ -399,6 +414,18 @@ monotime_diff_nsec(const monotime_t *start,
   return diff_nsec;
 }
 
+/* This value is ONE_BILLION >> 20. */
+const uint32_t STAMP_TICKS_PER_SECOND = 953;
+
+uint32_t
+monotime_coarse_to_stamp(const monotime_coarse_t *t)
+{
+  uint32_t nsec = (uint32_t)t->ts_.tv_nsec;
+  uint32_t sec = (uint32_t)t->ts_.tv_sec;
+
+  return (sec * STAMP_TICKS_PER_SECOND) + (nsec >> 20);
+}
+
 /* end of "HAVE_CLOCK_GETTIME" */
 #elif defined (_WIN32)
 
@@ -531,6 +558,14 @@ monotime_coarse_diff_nsec(const monotime_coarse_t *start,
   return monotime_coarse_diff_msec(start, end) * ONE_MILLION;
 }
 
+const uint32_t STAMP_TICKS_PER_SECOND = 1000;
+
+uint32_t
+monotime_coarse_to_stamp(const monotime_coarse_t *t)
+{
+  return (uint32_t) t->tick_count;
+}
+
 /* end of "_WIN32" */
 #elif defined(MONOTIME_USING_GETTIMEOFDAY)
 
@@ -567,6 +602,17 @@ monotime_diff_nsec(const monotime_t *start,
   return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000);
 }
 
+/* This value is ONE_MILLION >> 10. */
+const uint32_t STAMP_TICKS_PER_SECOND = 976;
+
+uint32_t
+monotime_coarse_to_stamp(const monotime_coarse_t *t)
+{
+  const uint32_t usec = (uint32_t)t->tv_.tv_usec;
+  const uint32_t sec = (uint32_t)t->tv_.tv_sec;
+  return (sec * STAMP_TICKS_PER_SECOND) | (nsec >> 10);
+}
+
 /* end of "MONOTIME_USING_GETTIMEOFDAY" */
 #else
 #error "No way to implement monotonic timers."
@@ -653,5 +699,35 @@ monotime_coarse_absolute_msec(void)
 {
   return monotime_coarse_absolute_nsec() / ONE_MILLION;
 }
+#else
+#define initalized_at_coarse initialized_at
 #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */
 
+/**
+ * Return the current time "stamp" as described by monotime_coarse_to_stamp.
+ */
+uint32_t
+monotime_coarse_get_stamp(void)
+{
+  monotime_coarse_t now;
+  monotime_coarse_get(&now);
+  return monotime_coarse_to_stamp(&now);
+}
+
+#ifdef __APPLE__
+uint64_t
+monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
+{
+  /* Recover as much precision as we can. */
+  uint64_t abstime_diff = (units << monotime_shift);
+  return (abstime_diff * mach_time_info.numer) /
+    (mach_time_info.denom * ONE_MILLION);
+}
+#else
+uint64_t
+monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
+{
+  return (units * 1000) / STAMP_TICKS_PER_SECOND;
+}
+#endif
+
diff --git a/src/common/compat_time.h b/src/common/compat_time.h
index 5ea4aae42..462dcecce 100644
--- a/src/common/compat_time.h
+++ b/src/common/compat_time.h
@@ -117,6 +117,23 @@ uint64_t monotime_coarse_absolute_msec(void);
 #define monotime_coarse_absolute_msec monotime_absolute_msec
 #endif /* 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 monotime_coarse_to_stamp(const monotime_coarse_t *t);
+/**
+ * Convert a difference, expressed in the units of monotime_coarse_to_stamp,
+ * into an approximate number of milliseconds.
+ */
+uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units);
+uint32_t monotime_coarse_get_stamp(void);
+
 #if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT)
 int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start,
     const monotime_coarse_t *end);
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index d37d986f1..fa19c0afd 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -2176,12 +2176,12 @@ n_cells_in_circ_queues(const circuit_t *c)
 }
 
 /**
- * Return the age of the oldest cell queued on <b>c</b>, in milliseconds.
+ * Return the age of the oldest cell queued on <b>c</b>, in timestamp units.
  * Return 0 if there are no cells queued on c.  Requires that <b>now</b> be
- * the current time in milliseconds since the epoch, truncated.
+ * the current coarse timestamp.
  *
  * This function will return incorrect results if the oldest cell queued on
- * the circuit is older than 2**32 msec (about 49 days) old.
+ * the circuit is older than about 2**32 msec (about 49 days) old.
  */
 STATIC uint32_t
 circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
@@ -2190,12 +2190,12 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
   packed_cell_t *cell;
 
   if (NULL != (cell = TOR_SIMPLEQ_FIRST(&c->n_chan_cells.head)))
-    age = now - cell->inserted_time;
+    age = now - cell->inserted_timestamp;
 
   if (! CIRCUIT_IS_ORIGIN(c)) {
     const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c);
     if (NULL != (cell = TOR_SIMPLEQ_FIRST(&orcirc->p_chan_cells.head))) {
-      uint32_t age2 = now - cell->inserted_time;
+      uint32_t age2 = now - cell->inserted_timestamp;
       if (age2 > age)
         return age2;
     }
@@ -2203,31 +2203,30 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
   return age;
 }
 
-/** Return the age in milliseconds of the oldest buffer chunk on <b>conn</b>,
- * where age is taken in milliseconds before the time <b>now</b> (in truncated
- * absolute monotonic msec).  If the connection has no data, treat
- * it as having age zero.
+/** Return the age of the oldest buffer chunk on <b>conn</b>, where age is
+ * taken in timestamp units before the time <b>now</b>.  If the connection has
+ * no data, treat it as having age zero.
  **/
 static uint32_t
-conn_get_buffer_age(const connection_t *conn, uint32_t now)
+conn_get_buffer_age(const connection_t *conn, uint32_t now_ts)
 {
   uint32_t age = 0, age2;
   if (conn->outbuf) {
-    age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now);
+    age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now_ts);
     if (age2 > age)
       age = age2;
   }
   if (conn->inbuf) {
-    age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now);
+    age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now_ts);
     if (age2 > age)
       age = age2;
   }
   return age;
 }
 
-/** Return the age in milliseconds of the oldest buffer chunk on any stream in
- * the linked list <b>stream</b>, where age is taken in milliseconds before
- * the time <b>now</b> (in truncated milliseconds since the epoch). */
+/** Return the age in timestamp units of the oldest buffer chunk on any stream
+ * in the linked list <b>stream</b>, where age is taken in timestamp units
+ * before the timestamp <b>now</b>. */
 static uint32_t
 circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now)
 {
@@ -2246,9 +2245,9 @@ circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now)
   return age;
 }
 
-/** Return the age in milliseconds of the oldest buffer chunk on any stream
- * attached to the circuit <b>c</b>, where age is taken in milliseconds before
- * the time <b>now</b> (in truncated milliseconds since the epoch). */
+/** Return the age in timestamp units of the oldest buffer chunk on any stream
+ * attached to the circuit <b>c</b>, where age is taken before the timestamp
+ * <b>now</b>. */
 STATIC uint32_t
 circuit_max_queued_data_age(const circuit_t *c, uint32_t now)
 {
@@ -2262,8 +2261,8 @@ circuit_max_queued_data_age(const circuit_t *c, uint32_t now)
 }
 
 /** Return the age of the oldest cell or stream buffer chunk on the circuit
- * <b>c</b>, where age is taken in milliseconds before the time <b>now</b> (in
- * truncated milliseconds since the epoch). */
+ * <b>c</b>, where age is taken in timestamp units before the timestamp
+ * <b>now</b> */
 STATIC uint32_t
 circuit_max_queued_item_age(const circuit_t *c, uint32_t now)
 {
@@ -2293,7 +2292,7 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_)
     return -1;
 }
 
-static uint32_t now_ms_for_buf_cmp;
+static uint32_t now_ts_for_buf_cmp;
 
 /** Helper to sort a list of circuit_t by age of oldest item, in descending
  * order. */
@@ -2302,8 +2301,8 @@ conns_compare_by_buffer_age_(const void **a_, const void **b_)
 {
   const connection_t *a = *a_;
   const connection_t *b = *b_;
-  time_t age_a = conn_get_buffer_age(a, now_ms_for_buf_cmp);
-  time_t age_b = conn_get_buffer_age(b, now_ms_for_buf_cmp);
+  time_t age_a = conn_get_buffer_age(a, now_ts_for_buf_cmp);
+  time_t age_b = conn_get_buffer_age(b, now_ts_for_buf_cmp);
 
   if (age_a < age_b)
     return 1;
@@ -2328,7 +2327,7 @@ circuits_handle_oom(size_t current_allocation)
   size_t mem_recovered=0;
   int n_circuits_killed=0;
   int n_dirconns_killed=0;
-  uint32_t now_ms;
+  uint32_t now_ts;
   log_notice(LD_GENERAL, "We're low on memory.  Killing circuits with "
              "over-long queues. (This behavior is controlled by "
              "MaxMemInQueues.)");
@@ -2341,11 +2340,11 @@ circuits_handle_oom(size_t current_allocation)
     mem_to_recover = current_allocation - mem_target;
   }
 
-  now_ms = (uint32_t)monotime_coarse_absolute_msec();
+  now_ts = monotime_coarse_get_stamp();
 
   circlist = circuit_get_global_list();
   SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
-    circ->age_tmp = circuit_max_queued_item_age(circ, now_ms);
+    circ->age_tmp = circuit_max_queued_item_age(circ, now_ts);
   } SMARTLIST_FOREACH_END(circ);
 
   /* This is O(n log n); there are faster algorithms we could use instead.
@@ -2358,9 +2357,9 @@ circuits_handle_oom(size_t current_allocation)
   } SMARTLIST_FOREACH_END(circ);
 
   /* Now sort the connection array ... */
-  now_ms_for_buf_cmp = now_ms;
+  now_ts_for_buf_cmp = now_ts;
   smartlist_sort(connection_array, conns_compare_by_buffer_age_);
-  now_ms_for_buf_cmp = 0;
+  now_ts_for_buf_cmp = 0;
 
   /* Fix up the connection array to its new order. */
   SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
@@ -2379,7 +2378,7 @@ circuits_handle_oom(size_t current_allocation)
      * data older than this circuit. */
     while (conn_idx < smartlist_len(connection_array)) {
       connection_t *conn = smartlist_get(connection_array, conn_idx);
-      uint32_t conn_age = conn_get_buffer_age(conn, now_ms);
+      uint32_t conn_age = conn_get_buffer_age(conn, now_ts);
       if (conn_age < circ->age_tmp) {
         break;
       }
diff --git a/src/or/or.h b/src/or/or.h
index 809714b5e..59cceb72c 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1166,8 +1166,8 @@ typedef struct packed_cell_t {
   /** Next cell queued on this circuit. */
   TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
   char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
-  uint32_t inserted_time; /**< Time (in milliseconds since epoch, with high
-                           * bits truncated) when this cell was inserted. */
+  uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
+                                * was inserted */
 } packed_cell_t;
 
 /** A queue of cells on a circuit, waiting to be added to the
diff --git a/src/or/relay.c b/src/or/relay.c
index 09f70793d..bbaf4ee78 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -2482,7 +2482,7 @@ cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
   (void)exitward;
   (void)use_stats;
 
-  copy->inserted_time = (uint32_t) monotime_coarse_absolute_msec();
+  copy->inserted_timestamp = monotime_coarse_get_stamp();
 
   cell_queue_append(queue, copy);
 }
@@ -2789,9 +2789,10 @@ channel_flush_from_first_active_circuit, (channel_t *chan, int max))
     /* Calculate the exact time that this cell has spent in the queue. */
     if (get_options()->CellStatistics ||
         get_options()->TestingEnableCellStatsEvent) {
-      uint32_t msec_waiting;
-      uint32_t msec_now = (uint32_t)monotime_coarse_absolute_msec();
-      msec_waiting = msec_now - cell->inserted_time;
+      uint32_t timestamp_now = monotime_coarse_get_stamp();
+      uint32_t msec_waiting =
+        (uint32_t) monotime_coarse_stamp_units_to_approx_msec(
+                         timestamp_now - cell->inserted_timestamp);
 
       if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
         or_circ = TO_OR_CIRCUIT(circ);
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index 9f4e19bc5..057d9fa2d 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -450,52 +450,54 @@ test_buffer_time_tracking(void *arg)
   tt_assert(buf);
 
   monotime_coarse_set_mock_time_nsec(START_NSEC);
-  const uint32_t START_MSEC = (uint32_t)monotime_coarse_absolute_msec();
+  const uint32_t START_TS = monotime_coarse_get_stamp();
 
   /* Empty buffer means the timestamp is 0. */
-  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC));
-  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
+  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS));
+  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+1000));
 
   buf_add(buf, "ABCDEFG", 7);
-  tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
+  tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+1000));
 
   buf2 = buf_copy(buf);
   tt_assert(buf2);
   tt_int_op(1234, OP_EQ,
-            buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234));
+            buf_get_oldest_chunk_timestamp(buf2, START_TS+1234));
 
   /* Now add more bytes; enough to overflow the first chunk. */
   monotime_coarse_set_mock_time_nsec(START_NSEC + 123 * (uint64_t)1000000);
+  const uint32_t TS2 = monotime_coarse_get_stamp();
   for (i = 0; i < 600; ++i)
     buf_add(buf, "ABCDEFG", 7);
   tt_int_op(4207, OP_EQ, buf_datalen(buf));
 
   /* The oldest bytes are still in the front. */
-  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
+  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+2000));
 
   /* Once those bytes are dropped, the chunk is still on the first
    * timestamp. */
   buf_get_bytes(buf, tmp, 100);
-  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
+  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+2000));
 
   /* But once we discard the whole first chunk, we get the data in the second
    * chunk. */
   buf_get_bytes(buf, tmp, 4000);
   tt_int_op(107, OP_EQ, buf_datalen(buf));
-  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
+  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS2+2000));
 
   /* This time we'll be grabbing a chunk from the freelist, and making sure
      its time gets updated */
   monotime_coarse_set_mock_time_nsec(START_NSEC + 5617 * (uint64_t)1000000);
+  const uint32_t TS3 = monotime_coarse_get_stamp();
   for (i = 0; i < 600; ++i)
     buf_add(buf, "ABCDEFG", 7);
   tt_int_op(4307, OP_EQ, buf_datalen(buf));
 
-  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
+  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS2+2000));
   buf_get_bytes(buf, tmp, 4000);
   buf_get_bytes(buf, tmp, 306);
-  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617));
-  tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000));
+  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS3));
+  tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS3+383));
 
  done:
   buf_free(buf);
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index cf28690a2..ad590b843 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -202,7 +202,7 @@ test_oom_streambuf(void *arg)
 {
   or_options_t *options = get_options_mutable();
   circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL, *c5 = NULL;
-  uint32_t tvms;
+  uint32_t tvts;
   int i;
   smartlist_t *edgeconns = smartlist_new();
   const uint64_t start_ns = 1389641159 * (uint64_t)1000000000;
@@ -222,6 +222,7 @@ test_oom_streambuf(void *arg)
   tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
 
   monotime_coarse_set_mock_time_nsec(start_ns);
+  const uint32_t ts_start = monotime_coarse_get_stamp();
 
   /* Start all circuits with a bit of data queued in cells */
 
@@ -270,22 +271,24 @@ test_oom_streambuf(void *arg)
   now_ns -= now_ns % 1000000000;
   now_ns += 1000000000;
   monotime_coarse_set_mock_time_nsec(now_ns);
-  tvms = (uint32_t) monotime_coarse_absolute_msec();
+  tvts = monotime_coarse_get_stamp();
+  const uint32_t diff = tvts - ts_start;
+  printf("\n!!!! %u\n", (unsigned) diff);
 
-  tt_int_op(circuit_max_queued_cell_age(c1, tvms), OP_EQ, 500);
-  tt_int_op(circuit_max_queued_cell_age(c2, tvms), OP_EQ, 490);
-  tt_int_op(circuit_max_queued_cell_age(c3, tvms), OP_EQ, 480);
-  tt_int_op(circuit_max_queued_cell_age(c4, tvms), OP_EQ, 0);
+  tt_int_op(circuit_max_queued_cell_age(c1, tvts), OP_EQ, 500);
+  tt_int_op(circuit_max_queued_cell_age(c2, tvts), OP_EQ, 490);
+  tt_int_op(circuit_max_queued_cell_age(c3, tvts), OP_EQ, 480);
+  tt_int_op(circuit_max_queued_cell_age(c4, tvts), OP_EQ, 0);
 
-  tt_int_op(circuit_max_queued_data_age(c1, tvms), OP_EQ, 390);
-  tt_int_op(circuit_max_queued_data_age(c2, tvms), OP_EQ, 380);
-  tt_int_op(circuit_max_queued_data_age(c3, tvms), OP_EQ, 0);
-  tt_int_op(circuit_max_queued_data_age(c4, tvms), OP_EQ, 370);
+  tt_int_op(circuit_max_queued_data_age(c1, tvts), OP_EQ, 390);
+  tt_int_op(circuit_max_queued_data_age(c2, tvts), OP_EQ, 380);
+  tt_int_op(circuit_max_queued_data_age(c3, tvts), OP_EQ, 0);
+  tt_int_op(circuit_max_queued_data_age(c4, tvts), OP_EQ, 370);
 
-  tt_int_op(circuit_max_queued_item_age(c1, tvms), OP_EQ, 500);
-  tt_int_op(circuit_max_queued_item_age(c2, tvms), OP_EQ, 490);
-  tt_int_op(circuit_max_queued_item_age(c3, tvms), OP_EQ, 480);
-  tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 370);
+  tt_int_op(circuit_max_queued_item_age(c1, tvts), OP_EQ, 500);
+  tt_int_op(circuit_max_queued_item_age(c2, tvts), OP_EQ, 490);
+  tt_int_op(circuit_max_queued_item_age(c3, tvts), OP_EQ, 480);
+  tt_int_op(circuit_max_queued_item_age(c4, tvts), OP_EQ, 370);
 
   tt_int_op(cell_queues_get_total_allocation(), OP_EQ,
             packed_cell_mem_cost() * 80);
@@ -301,7 +304,7 @@ test_oom_streambuf(void *arg)
     smartlist_add(edgeconns, ec);
   }
   tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*17*2);
-  tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 1000);
+  tt_int_op(circuit_max_queued_item_age(c4, tvts), OP_EQ, 1000);
 
   tt_int_op(cell_queues_check_size(), OP_EQ, 0);
 
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 0519a4758..7856b506b 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -5801,6 +5801,7 @@ test_util_monotonic_time(void *arg)
   monotime_coarse_t mtc1, mtc2;
   uint64_t nsec1, nsec2, usec1, msec1;
   uint64_t nsecc1, nsecc2, usecc1, msecc1;
+  uint32_t stamp1, stamp2;
 
   monotime_init();
 
@@ -5812,6 +5813,7 @@ test_util_monotonic_time(void *arg)
   nsecc1 = monotime_coarse_absolute_nsec();
   usecc1 = monotime_coarse_absolute_usec();
   msecc1 = monotime_coarse_absolute_msec();
+  stamp1 = monotime_coarse_to_stamp(&mtc1);
 
   tor_sleep_msec(200);
 
@@ -5819,6 +5821,7 @@ test_util_monotonic_time(void *arg)
   monotime_coarse_get(&mtc2);
   nsec2 = monotime_absolute_nsec();
   nsecc2 = monotime_coarse_absolute_nsec();
+  stamp2 = monotime_coarse_to_stamp(&mtc2);
 
   /* We need to be a little careful here since we don't know the system load.
    */
@@ -5840,6 +5843,11 @@ test_util_monotonic_time(void *arg)
   tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 1);
   tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 1000);
 
+  uint64_t coarse_stamp_diff =
+    monotime_coarse_stamp_units_to_approx_msec(stamp2-stamp1);
+  tt_u64_op(coarse_stamp_diff, OP_GE, 120);
+  tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
+
  done:
   ;
 }





More information about the tor-commits mailing list