diff options
Diffstat (limited to 'src/or/circuitlist.c')
-rw-r--r-- | src/or/circuitlist.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 90fc93f3a..a2dd07fbe 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -59,6 +59,8 @@ typedef struct chan_circid_circuit_map_t { channel_t *chan; circid_t circ_id; circuit_t *circuit; + /* For debugging 12184: when was this placeholder item added? */ + time_t made_placeholder_at; } chan_circid_circuit_map_t; /** Helper for hash tables: compare the channel and circuit ID for a and @@ -76,7 +78,15 @@ chan_circid_entries_eq_(chan_circid_circuit_map_t *a, static INLINE unsigned int chan_circid_entry_hash_(chan_circid_circuit_map_t *a) { - return ((unsigned)a->circ_id) ^ (unsigned)(uintptr_t)(a->chan); + /* Try to squeze the siphash input into 8 bytes to save any extra siphash + * rounds. This hash function is in the critical path. */ + uintptr_t chan = (uintptr_t) (void*) a->chan; + uint32_t array[2]; + array[0] = a->circ_id; + /* The low bits of the channel pointer are uninteresting, since the channel + * is a pretty big structure. */ + array[1] = (uint32_t) (chan >> 6); + return (unsigned) siphash24g(array, sizeof(array)); } /** Map from [chan,circid] to circuit. */ @@ -176,6 +186,7 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction, found = HT_FIND(chan_circid_map, &chan_circid_map, &search); if (found) { found->circuit = circ; + found->made_placeholder_at = 0; } else { found = tor_malloc_zero(sizeof(chan_circid_circuit_map_t)); found->circ_id = id; @@ -233,11 +244,14 @@ channel_mark_circid_unusable(channel_t *chan, circid_t id) "a circuit there.", (unsigned)id, chan); } else if (ent) { /* It's already marked. */ + if (!ent->made_placeholder_at) + ent->made_placeholder_at = approx_time(); } else { ent = tor_malloc_zero(sizeof(chan_circid_circuit_map_t)); ent->chan = chan; ent->circ_id = id; - /* leave circuit at NULL */ + /* leave circuit at NULL. */ + ent->made_placeholder_at = approx_time(); HT_INSERT(chan_circid_map, &chan_circid_map, ent); } } @@ -320,10 +334,13 @@ circuit_set_p_circid_chan(or_circuit_t *or_circ, circid_t id, circuit_set_circid_chan_helper(circ, CELL_DIRECTION_IN, id, chan); - if (chan) + if (chan) { tor_assert(bool_eq(or_circ->p_chan_cells.n, or_circ->next_active_on_p_chan)); + chan->timestamp_last_had_circuits = approx_time(); + } + if (circ->p_delete_pending && old_chan) { channel_mark_circid_unusable(old_chan, old_id); circ->p_delete_pending = 0; @@ -342,9 +359,12 @@ circuit_set_n_circid_chan(circuit_t *circ, circid_t id, circuit_set_circid_chan_helper(circ, CELL_DIRECTION_OUT, id, chan); - if (chan) + if (chan) { tor_assert(bool_eq(circ->n_chan_cells.n, circ->next_active_on_n_chan)); + chan->timestamp_last_had_circuits = approx_time(); + } + if (circ->n_delete_pending && old_chan) { channel_mark_circid_unusable(old_chan, old_id); circ->n_delete_pending = 0; @@ -1082,6 +1102,27 @@ circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan) return 0; } +/** Helper for debugging 12184. Returns the time since which 'circ_id' has + * been marked unusable on 'chan'. */ +time_t +circuit_id_when_marked_unusable_on_channel(circid_t circ_id, channel_t *chan) +{ + chan_circid_circuit_map_t search; + chan_circid_circuit_map_t *found; + + memset(&search, 0, sizeof(search)); + search.circ_id = circ_id; + search.chan = chan; + + found = HT_FIND(chan_circid_map, &chan_circid_map, &search); + + if (! found || found->circuit) + return 0; + + return found->made_placeholder_at; +} + + /** Return the circuit that a given edge connection is using. */ circuit_t * circuit_get_by_edge_conn(edge_connection_t *conn) @@ -1975,7 +2016,9 @@ circuits_handle_oom(size_t current_allocation) break; } SMARTLIST_FOREACH_END(circ); +#ifdef ENABLE_MEMPOOLS clean_cell_pool(); /* In case this helps. */ +#endif /* ENABLE_MEMPOOLS */ buf_shrink_freelists(1); /* This is necessary to actually release buffer chunks. */ |