mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-14 07:03:44 +01:00
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.
This commit is contained in:
parent
da82e0b579
commit
c3c0a05f51
@ -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);
|
||||||
@ -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)
|
||||||
|
@ -79,8 +79,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;
|
||||||
|
@ -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)
|
||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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)
|
||||||
|
|
||||||
@ -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)
|
||||||
|
|
||||||
@ -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)
|
||||||
|
|
||||||
@ -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."
|
||||||
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
@ -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. */
|
||||||
@ -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;
|
||||||
@ -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.)");
|
||||||
@ -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.
|
||||||
@ -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) {
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1166,8 +1166,8 @@ typedef struct packed_cell_t {
|
|||||||
/** Next cell queued on this circuit. */
|
/** Next cell queued on this circuit. */
|
||||||
TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
|
TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
|
||||||
char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
|
char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
|
||||||
uint32_t inserted_time; /**< Time (in milliseconds since epoch, with high
|
uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
|
||||||
* bits truncated) when this cell was inserted. */
|
* was inserted */
|
||||||
} packed_cell_t;
|
} packed_cell_t;
|
||||||
|
|
||||||
/** A queue of cells on a circuit, waiting to be added to the
|
/** A queue of cells on a circuit, waiting to be added to the
|
||||||
|
@ -2482,7 +2482,7 @@ cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
|||||||
(void)exitward;
|
(void)exitward;
|
||||||
(void)use_stats;
|
(void)use_stats;
|
||||||
|
|
||||||
copy->inserted_time = (uint32_t) monotime_coarse_absolute_msec();
|
copy->inserted_timestamp = monotime_coarse_get_stamp();
|
||||||
|
|
||||||
cell_queue_append(queue, copy);
|
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. */
|
/* Calculate the exact time that this cell has spent in the queue. */
|
||||||
if (get_options()->CellStatistics ||
|
if (get_options()->CellStatistics ||
|
||||||
get_options()->TestingEnableCellStatsEvent) {
|
get_options()->TestingEnableCellStatsEvent) {
|
||||||
uint32_t msec_waiting;
|
uint32_t timestamp_now = monotime_coarse_get_stamp();
|
||||||
uint32_t msec_now = (uint32_t)monotime_coarse_absolute_msec();
|
uint32_t msec_waiting =
|
||||||
msec_waiting = msec_now - cell->inserted_time;
|
(uint32_t) monotime_coarse_stamp_units_to_approx_msec(
|
||||||
|
timestamp_now - cell->inserted_timestamp);
|
||||||
|
|
||||||
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
|
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
or_circ = TO_OR_CIRCUIT(circ);
|
or_circ = TO_OR_CIRCUIT(circ);
|
||||||
|
@ -450,52 +450,54 @@ test_buffer_time_tracking(void *arg)
|
|||||||
tt_assert(buf);
|
tt_assert(buf);
|
||||||
|
|
||||||
monotime_coarse_set_mock_time_nsec(START_NSEC);
|
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. */
|
/* 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_TS));
|
||||||
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+1000));
|
||||||
|
|
||||||
buf_add(buf, "ABCDEFG", 7);
|
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);
|
buf2 = buf_copy(buf);
|
||||||
tt_assert(buf2);
|
tt_assert(buf2);
|
||||||
tt_int_op(1234, OP_EQ,
|
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. */
|
/* Now add more bytes; enough to overflow the first chunk. */
|
||||||
monotime_coarse_set_mock_time_nsec(START_NSEC + 123 * (uint64_t)1000000);
|
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)
|
for (i = 0; i < 600; ++i)
|
||||||
buf_add(buf, "ABCDEFG", 7);
|
buf_add(buf, "ABCDEFG", 7);
|
||||||
tt_int_op(4207, OP_EQ, buf_datalen(buf));
|
tt_int_op(4207, OP_EQ, buf_datalen(buf));
|
||||||
|
|
||||||
/* The oldest bytes are still in the front. */
|
/* 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
|
/* Once those bytes are dropped, the chunk is still on the first
|
||||||
* timestamp. */
|
* timestamp. */
|
||||||
buf_get_bytes(buf, tmp, 100);
|
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
|
/* But once we discard the whole first chunk, we get the data in the second
|
||||||
* chunk. */
|
* chunk. */
|
||||||
buf_get_bytes(buf, tmp, 4000);
|
buf_get_bytes(buf, tmp, 4000);
|
||||||
tt_int_op(107, OP_EQ, buf_datalen(buf));
|
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
|
/* This time we'll be grabbing a chunk from the freelist, and making sure
|
||||||
its time gets updated */
|
its time gets updated */
|
||||||
monotime_coarse_set_mock_time_nsec(START_NSEC + 5617 * (uint64_t)1000000);
|
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)
|
for (i = 0; i < 600; ++i)
|
||||||
buf_add(buf, "ABCDEFG", 7);
|
buf_add(buf, "ABCDEFG", 7);
|
||||||
tt_int_op(4307, OP_EQ, buf_datalen(buf));
|
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, 4000);
|
||||||
buf_get_bytes(buf, tmp, 306);
|
buf_get_bytes(buf, tmp, 306);
|
||||||
tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617));
|
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, START_MSEC+6000));
|
tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS3+383));
|
||||||
|
|
||||||
done:
|
done:
|
||||||
buf_free(buf);
|
buf_free(buf);
|
||||||
|
@ -202,7 +202,7 @@ test_oom_streambuf(void *arg)
|
|||||||
{
|
{
|
||||||
or_options_t *options = get_options_mutable();
|
or_options_t *options = get_options_mutable();
|
||||||
circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL, *c5 = NULL;
|
circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL, *c5 = NULL;
|
||||||
uint32_t tvms;
|
uint32_t tvts;
|
||||||
int i;
|
int i;
|
||||||
smartlist_t *edgeconns = smartlist_new();
|
smartlist_t *edgeconns = smartlist_new();
|
||||||
const uint64_t start_ns = 1389641159 * (uint64_t)1000000000;
|
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);
|
tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
|
||||||
|
|
||||||
monotime_coarse_set_mock_time_nsec(start_ns);
|
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 */
|
/* 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 -= now_ns % 1000000000;
|
||||||
now_ns += 1000000000;
|
now_ns += 1000000000;
|
||||||
monotime_coarse_set_mock_time_nsec(now_ns);
|
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(c1, tvts), OP_EQ, 500);
|
||||||
tt_int_op(circuit_max_queued_cell_age(c2, tvms), OP_EQ, 490);
|
tt_int_op(circuit_max_queued_cell_age(c2, tvts), OP_EQ, 490);
|
||||||
tt_int_op(circuit_max_queued_cell_age(c3, tvms), OP_EQ, 480);
|
tt_int_op(circuit_max_queued_cell_age(c3, tvts), OP_EQ, 480);
|
||||||
tt_int_op(circuit_max_queued_cell_age(c4, tvms), OP_EQ, 0);
|
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(c1, tvts), OP_EQ, 390);
|
||||||
tt_int_op(circuit_max_queued_data_age(c2, tvms), OP_EQ, 380);
|
tt_int_op(circuit_max_queued_data_age(c2, tvts), OP_EQ, 380);
|
||||||
tt_int_op(circuit_max_queued_data_age(c3, tvms), OP_EQ, 0);
|
tt_int_op(circuit_max_queued_data_age(c3, tvts), OP_EQ, 0);
|
||||||
tt_int_op(circuit_max_queued_data_age(c4, tvms), OP_EQ, 370);
|
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(c1, tvts), OP_EQ, 500);
|
||||||
tt_int_op(circuit_max_queued_item_age(c2, tvms), OP_EQ, 490);
|
tt_int_op(circuit_max_queued_item_age(c2, tvts), OP_EQ, 490);
|
||||||
tt_int_op(circuit_max_queued_item_age(c3, tvms), OP_EQ, 480);
|
tt_int_op(circuit_max_queued_item_age(c3, tvts), OP_EQ, 480);
|
||||||
tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 370);
|
tt_int_op(circuit_max_queued_item_age(c4, tvts), OP_EQ, 370);
|
||||||
|
|
||||||
tt_int_op(cell_queues_get_total_allocation(), OP_EQ,
|
tt_int_op(cell_queues_get_total_allocation(), OP_EQ,
|
||||||
packed_cell_mem_cost() * 80);
|
packed_cell_mem_cost() * 80);
|
||||||
@ -301,7 +304,7 @@ test_oom_streambuf(void *arg)
|
|||||||
smartlist_add(edgeconns, ec);
|
smartlist_add(edgeconns, ec);
|
||||||
}
|
}
|
||||||
tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*17*2);
|
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);
|
tt_int_op(cell_queues_check_size(), OP_EQ, 0);
|
||||||
|
|
||||||
|
@ -5801,6 +5801,7 @@ test_util_monotonic_time(void *arg)
|
|||||||
monotime_coarse_t mtc1, mtc2;
|
monotime_coarse_t mtc1, mtc2;
|
||||||
uint64_t nsec1, nsec2, usec1, msec1;
|
uint64_t nsec1, nsec2, usec1, msec1;
|
||||||
uint64_t nsecc1, nsecc2, usecc1, msecc1;
|
uint64_t nsecc1, nsecc2, usecc1, msecc1;
|
||||||
|
uint32_t stamp1, stamp2;
|
||||||
|
|
||||||
monotime_init();
|
monotime_init();
|
||||||
|
|
||||||
@ -5812,6 +5813,7 @@ test_util_monotonic_time(void *arg)
|
|||||||
nsecc1 = monotime_coarse_absolute_nsec();
|
nsecc1 = monotime_coarse_absolute_nsec();
|
||||||
usecc1 = monotime_coarse_absolute_usec();
|
usecc1 = monotime_coarse_absolute_usec();
|
||||||
msecc1 = monotime_coarse_absolute_msec();
|
msecc1 = monotime_coarse_absolute_msec();
|
||||||
|
stamp1 = monotime_coarse_to_stamp(&mtc1);
|
||||||
|
|
||||||
tor_sleep_msec(200);
|
tor_sleep_msec(200);
|
||||||
|
|
||||||
@ -5819,6 +5821,7 @@ test_util_monotonic_time(void *arg)
|
|||||||
monotime_coarse_get(&mtc2);
|
monotime_coarse_get(&mtc2);
|
||||||
nsec2 = monotime_absolute_nsec();
|
nsec2 = monotime_absolute_nsec();
|
||||||
nsecc2 = monotime_coarse_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.
|
/* 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(msecc1, OP_LE, nsecc1 / 1000000 + 1);
|
||||||
tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 1000);
|
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:
|
done:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user