Loading src/common/buffers.c +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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 = 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) { if (buf->tail) { tor_assert(buf->head); tor_assert(buf->head); Loading @@ -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 /** Return the age of the oldest chunk in the buffer <b>buf</b>, in * milliseconds. Requires the current monotonic time, in truncated msec, * timestamp units. Requires the current monotonic timestamp as its * as its input <b>now</b>. * input <b>now</b>. */ */ uint32_t uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now) buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now) Loading src/common/buffers.h +1 −2 Original line number Original line Diff line number Diff line Loading @@ -86,8 +86,7 @@ typedef struct chunk_t { size_t DBG_alloc; size_t DBG_alloc; #endif #endif char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */ 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 uint32_t inserted_time; /**< Timestamp when this chunk was inserted. */ * when this chunk was inserted. */ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in * this chunk. */ * this chunk. */ } chunk_t; } chunk_t; Loading src/common/compat_time.c +76 −0 Original line number Original line Diff line number Diff line Loading @@ -279,6 +279,7 @@ monotime_reset_ratchets_for_testing(void) * nanoseconds. * nanoseconds. */ */ static struct mach_timebase_info mach_time_info; static struct mach_timebase_info mach_time_info; static int monotime_shift = 0; static void static void monotime_init_internal(void) monotime_init_internal(void) Loading @@ -287,6 +288,14 @@ monotime_init_internal(void) int r = mach_timebase_info(&mach_time_info); int r = mach_timebase_info(&mach_time_info); tor_assert(r == 0); tor_assert(r == 0); tor_assert(mach_time_info.denom != 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); } } } /** /** Loading Loading @@ -321,6 +330,12 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; return diff_nsec; } } uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t) { return (uint32_t)(t->abstime_ >> monotime_shift); } /* end of "__APPLE__" */ /* end of "__APPLE__" */ #elif defined(HAVE_CLOCK_GETTIME) #elif defined(HAVE_CLOCK_GETTIME) Loading Loading @@ -399,6 +414,18 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; 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" */ /* end of "HAVE_CLOCK_GETTIME" */ #elif defined (_WIN32) #elif defined (_WIN32) Loading Loading @@ -531,6 +558,14 @@ monotime_coarse_diff_nsec(const monotime_coarse_t *start, return monotime_coarse_diff_msec(start, end) * ONE_MILLION; 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" */ /* end of "_WIN32" */ #elif defined(MONOTIME_USING_GETTIMEOFDAY) #elif defined(MONOTIME_USING_GETTIMEOFDAY) Loading Loading @@ -567,6 +602,17 @@ monotime_diff_nsec(const monotime_t *start, return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000); 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" */ /* end of "MONOTIME_USING_GETTIMEOFDAY" */ #else #else #error "No way to implement monotonic timers." #error "No way to implement monotonic timers." Loading Loading @@ -653,5 +699,35 @@ monotime_coarse_absolute_msec(void) { { return monotime_coarse_absolute_nsec() / ONE_MILLION; return monotime_coarse_absolute_nsec() / ONE_MILLION; } } #else #define initalized_at_coarse initialized_at #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ #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 src/common/compat_time.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -117,6 +117,23 @@ uint64_t monotime_coarse_absolute_msec(void); #define monotime_coarse_absolute_msec monotime_absolute_msec #define monotime_coarse_absolute_msec monotime_absolute_msec #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ #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) #if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start, int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start, const monotime_coarse_t *end); const monotime_coarse_t *end); Loading src/or/circuitlist.c +28 −29 Original line number Original line Diff line number Diff line Loading @@ -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 * 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 * 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 STATIC uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) Loading @@ -2190,12 +2190,12 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) packed_cell_t *cell; packed_cell_t *cell; if (NULL != (cell = TOR_SIMPLEQ_FIRST(&c->n_chan_cells.head))) 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)) { if (! CIRCUIT_IS_ORIGIN(c)) { const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c); const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c); if (NULL != (cell = TOR_SIMPLEQ_FIRST(&orcirc->p_chan_cells.head))) { 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) if (age2 > age) return age2; return age2; } } Loading @@ -2203,31 +2203,30 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) return age; return age; } } /** Return the age in milliseconds of the oldest buffer chunk on <b>conn</b>, /** Return the age of the oldest buffer chunk on <b>conn</b>, where age is * where age is taken in milliseconds before the time <b>now</b> (in truncated * taken in timestamp units before the time <b>now</b>. If the connection has * absolute monotonic msec). If the connection has no data, treat * no data, treat it as having age zero. * it as having age zero. **/ **/ static uint32_t 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; uint32_t age = 0, age2; if (conn->outbuf) { 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) if (age2 > age) age = age2; age = age2; } } if (conn->inbuf) { 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) if (age2 > age) age = age2; age = age2; } } return age; return age; } } /** Return the age in milliseconds of the oldest buffer chunk on any stream in /** Return the age in timestamp units of the oldest buffer chunk on any stream * the linked list <b>stream</b>, where age is taken in milliseconds before * in the linked list <b>stream</b>, where age is taken in timestamp units * the time <b>now</b> (in truncated milliseconds since the epoch). */ * before the timestamp <b>now</b>. */ static uint32_t static uint32_t circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) { { Loading @@ -2246,9 +2245,9 @@ circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) return age; return age; } } /** Return the age in milliseconds of the oldest buffer chunk on any stream /** 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 in milliseconds before * attached to the circuit <b>c</b>, where age is taken before the timestamp * the time <b>now</b> (in truncated milliseconds since the epoch). */ * <b>now</b>. */ STATIC uint32_t STATIC uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now) circuit_max_queued_data_age(const circuit_t *c, uint32_t now) { { Loading @@ -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 /** 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 * <b>c</b>, where age is taken in timestamp units before the timestamp * truncated milliseconds since the epoch). */ * <b>now</b> */ STATIC uint32_t STATIC uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now) circuit_max_queued_item_age(const circuit_t *c, uint32_t now) { { Loading Loading @@ -2293,7 +2292,7 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) return -1; 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 /** Helper to sort a list of circuit_t by age of oldest item, in descending * order. */ * order. */ Loading @@ -2302,8 +2301,8 @@ conns_compare_by_buffer_age_(const void **a_, const void **b_) { { const connection_t *a = *a_; const connection_t *a = *a_; const connection_t *b = *b_; const connection_t *b = *b_; time_t age_a = conn_get_buffer_age(a, 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_ms_for_buf_cmp); time_t age_b = conn_get_buffer_age(b, now_ts_for_buf_cmp); if (age_a < age_b) if (age_a < age_b) return 1; return 1; Loading @@ -2328,7 +2327,7 @@ circuits_handle_oom(size_t current_allocation) size_t mem_recovered=0; size_t mem_recovered=0; int n_circuits_killed=0; int n_circuits_killed=0; int n_dirconns_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 " log_notice(LD_GENERAL, "We're low on memory. Killing circuits with " "over-long queues. (This behavior is controlled by " "over-long queues. (This behavior is controlled by " "MaxMemInQueues.)"); "MaxMemInQueues.)"); Loading @@ -2341,11 +2340,11 @@ circuits_handle_oom(size_t current_allocation) mem_to_recover = current_allocation - mem_target; 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(); circlist = circuit_get_global_list(); SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { 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); } SMARTLIST_FOREACH_END(circ); /* This is O(n log n); there are faster algorithms we could use instead. /* This is O(n log n); there are faster algorithms we could use instead. Loading @@ -2358,9 +2357,9 @@ circuits_handle_oom(size_t current_allocation) } SMARTLIST_FOREACH_END(circ); } SMARTLIST_FOREACH_END(circ); /* Now sort the connection array ... */ /* 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_); 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. */ /* Fix up the connection array to its new order. */ SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { Loading @@ -2379,7 +2378,7 @@ circuits_handle_oom(size_t current_allocation) * data older than this circuit. */ * data older than this circuit. */ while (conn_idx < smartlist_len(connection_array)) { while (conn_idx < smartlist_len(connection_array)) { connection_t *conn = smartlist_get(connection_array, conn_idx); 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) { if (conn_age < circ->age_tmp) { break; break; } } Loading Loading
src/common/buffers.c +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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 = 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) { if (buf->tail) { tor_assert(buf->head); tor_assert(buf->head); Loading @@ -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 /** Return the age of the oldest chunk in the buffer <b>buf</b>, in * milliseconds. Requires the current monotonic time, in truncated msec, * timestamp units. Requires the current monotonic timestamp as its * as its input <b>now</b>. * input <b>now</b>. */ */ uint32_t uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now) buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now) Loading
src/common/buffers.h +1 −2 Original line number Original line Diff line number Diff line Loading @@ -86,8 +86,7 @@ typedef struct chunk_t { size_t DBG_alloc; size_t DBG_alloc; #endif #endif char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */ 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 uint32_t inserted_time; /**< Timestamp when this chunk was inserted. */ * when this chunk was inserted. */ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in * this chunk. */ * this chunk. */ } chunk_t; } chunk_t; Loading
src/common/compat_time.c +76 −0 Original line number Original line Diff line number Diff line Loading @@ -279,6 +279,7 @@ monotime_reset_ratchets_for_testing(void) * nanoseconds. * nanoseconds. */ */ static struct mach_timebase_info mach_time_info; static struct mach_timebase_info mach_time_info; static int monotime_shift = 0; static void static void monotime_init_internal(void) monotime_init_internal(void) Loading @@ -287,6 +288,14 @@ monotime_init_internal(void) int r = mach_timebase_info(&mach_time_info); int r = mach_timebase_info(&mach_time_info); tor_assert(r == 0); tor_assert(r == 0); tor_assert(mach_time_info.denom != 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); } } } /** /** Loading Loading @@ -321,6 +330,12 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; return diff_nsec; } } uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t) { return (uint32_t)(t->abstime_ >> monotime_shift); } /* end of "__APPLE__" */ /* end of "__APPLE__" */ #elif defined(HAVE_CLOCK_GETTIME) #elif defined(HAVE_CLOCK_GETTIME) Loading Loading @@ -399,6 +414,18 @@ monotime_diff_nsec(const monotime_t *start, return diff_nsec; 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" */ /* end of "HAVE_CLOCK_GETTIME" */ #elif defined (_WIN32) #elif defined (_WIN32) Loading Loading @@ -531,6 +558,14 @@ monotime_coarse_diff_nsec(const monotime_coarse_t *start, return monotime_coarse_diff_msec(start, end) * ONE_MILLION; 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" */ /* end of "_WIN32" */ #elif defined(MONOTIME_USING_GETTIMEOFDAY) #elif defined(MONOTIME_USING_GETTIMEOFDAY) Loading Loading @@ -567,6 +602,17 @@ monotime_diff_nsec(const monotime_t *start, return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000); 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" */ /* end of "MONOTIME_USING_GETTIMEOFDAY" */ #else #else #error "No way to implement monotonic timers." #error "No way to implement monotonic timers." Loading Loading @@ -653,5 +699,35 @@ monotime_coarse_absolute_msec(void) { { return monotime_coarse_absolute_nsec() / ONE_MILLION; return monotime_coarse_absolute_nsec() / ONE_MILLION; } } #else #define initalized_at_coarse initialized_at #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ #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
src/common/compat_time.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -117,6 +117,23 @@ uint64_t monotime_coarse_absolute_msec(void); #define monotime_coarse_absolute_msec monotime_absolute_msec #define monotime_coarse_absolute_msec monotime_absolute_msec #endif /* defined(MONOTIME_COARSE_FN_IS_DIFFERENT) */ #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) #if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start, int64_t monotime_coarse_diff_nsec(const monotime_coarse_t *start, const monotime_coarse_t *end); const monotime_coarse_t *end); Loading
src/or/circuitlist.c +28 −29 Original line number Original line Diff line number Diff line Loading @@ -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 * 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 * 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 STATIC uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) Loading @@ -2190,12 +2190,12 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) packed_cell_t *cell; packed_cell_t *cell; if (NULL != (cell = TOR_SIMPLEQ_FIRST(&c->n_chan_cells.head))) 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)) { if (! CIRCUIT_IS_ORIGIN(c)) { const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c); const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c); if (NULL != (cell = TOR_SIMPLEQ_FIRST(&orcirc->p_chan_cells.head))) { 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) if (age2 > age) return age2; return age2; } } Loading @@ -2203,31 +2203,30 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) return age; return age; } } /** Return the age in milliseconds of the oldest buffer chunk on <b>conn</b>, /** Return the age of the oldest buffer chunk on <b>conn</b>, where age is * where age is taken in milliseconds before the time <b>now</b> (in truncated * taken in timestamp units before the time <b>now</b>. If the connection has * absolute monotonic msec). If the connection has no data, treat * no data, treat it as having age zero. * it as having age zero. **/ **/ static uint32_t 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; uint32_t age = 0, age2; if (conn->outbuf) { 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) if (age2 > age) age = age2; age = age2; } } if (conn->inbuf) { 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) if (age2 > age) age = age2; age = age2; } } return age; return age; } } /** Return the age in milliseconds of the oldest buffer chunk on any stream in /** Return the age in timestamp units of the oldest buffer chunk on any stream * the linked list <b>stream</b>, where age is taken in milliseconds before * in the linked list <b>stream</b>, where age is taken in timestamp units * the time <b>now</b> (in truncated milliseconds since the epoch). */ * before the timestamp <b>now</b>. */ static uint32_t static uint32_t circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) { { Loading @@ -2246,9 +2245,9 @@ circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) return age; return age; } } /** Return the age in milliseconds of the oldest buffer chunk on any stream /** 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 in milliseconds before * attached to the circuit <b>c</b>, where age is taken before the timestamp * the time <b>now</b> (in truncated milliseconds since the epoch). */ * <b>now</b>. */ STATIC uint32_t STATIC uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now) circuit_max_queued_data_age(const circuit_t *c, uint32_t now) { { Loading @@ -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 /** 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 * <b>c</b>, where age is taken in timestamp units before the timestamp * truncated milliseconds since the epoch). */ * <b>now</b> */ STATIC uint32_t STATIC uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now) circuit_max_queued_item_age(const circuit_t *c, uint32_t now) { { Loading Loading @@ -2293,7 +2292,7 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) return -1; 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 /** Helper to sort a list of circuit_t by age of oldest item, in descending * order. */ * order. */ Loading @@ -2302,8 +2301,8 @@ conns_compare_by_buffer_age_(const void **a_, const void **b_) { { const connection_t *a = *a_; const connection_t *a = *a_; const connection_t *b = *b_; const connection_t *b = *b_; time_t age_a = conn_get_buffer_age(a, 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_ms_for_buf_cmp); time_t age_b = conn_get_buffer_age(b, now_ts_for_buf_cmp); if (age_a < age_b) if (age_a < age_b) return 1; return 1; Loading @@ -2328,7 +2327,7 @@ circuits_handle_oom(size_t current_allocation) size_t mem_recovered=0; size_t mem_recovered=0; int n_circuits_killed=0; int n_circuits_killed=0; int n_dirconns_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 " log_notice(LD_GENERAL, "We're low on memory. Killing circuits with " "over-long queues. (This behavior is controlled by " "over-long queues. (This behavior is controlled by " "MaxMemInQueues.)"); "MaxMemInQueues.)"); Loading @@ -2341,11 +2340,11 @@ circuits_handle_oom(size_t current_allocation) mem_to_recover = current_allocation - mem_target; 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(); circlist = circuit_get_global_list(); SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { 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); } SMARTLIST_FOREACH_END(circ); /* This is O(n log n); there are faster algorithms we could use instead. /* This is O(n log n); there are faster algorithms we could use instead. Loading @@ -2358,9 +2357,9 @@ circuits_handle_oom(size_t current_allocation) } SMARTLIST_FOREACH_END(circ); } SMARTLIST_FOREACH_END(circ); /* Now sort the connection array ... */ /* 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_); 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. */ /* Fix up the connection array to its new order. */ SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { Loading @@ -2379,7 +2378,7 @@ circuits_handle_oom(size_t current_allocation) * data older than this circuit. */ * data older than this circuit. */ while (conn_idx < smartlist_len(connection_array)) { while (conn_idx < smartlist_len(connection_array)) { connection_t *conn = smartlist_get(connection_array, conn_idx); 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) { if (conn_age < circ->age_tmp) { break; break; } } Loading