Loading changes/ticket32196 0 → 100644 +2 −0 Original line number Diff line number Diff line o Testing (circuit, EWMA): - Add unit tests for circuitmux and EWMA subsystems. Closes ticket 32196. src/core/or/circuitmux.c +2 −54 Original line number Diff line number Diff line Loading @@ -69,26 +69,20 @@ * made to attach all existing circuits to the new policy. **/ #define CIRCUITMUX_PRIVATE #include "core/or/or.h" #include "core/or/channel.h" #include "core/or/circuitlist.h" #include "core/or/circuitmux.h" #include "core/or/relay.h" #include "core/or/cell_queue_st.h" #include "core/or/destroy_cell_queue_st.h" #include "core/or/or_circuit_st.h" /* * Private typedefs for circuitmux.c */ /* * Map of muxinfos for circuitmux_t to use; struct is defined below (name * of struct must match HT_HEAD line). */ typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t; /* * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to * break the hash table code). Loading @@ -102,49 +96,6 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t; typedef struct circuit_muxinfo_s circuit_muxinfo_t; /* * Structures for circuitmux.c */ struct circuitmux_s { /* Keep count of attached, active circuits */ unsigned int n_circuits, n_active_circuits; /* Total number of queued cells on all circuits */ unsigned int n_cells; /* * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t */ chanid_circid_muxinfo_map_t *chanid_circid_map; /** List of queued destroy cells */ destroy_cell_queue_t destroy_cell_queue; /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit * returned the destroy queue. Used to force alternation between * destroy/non-destroy cells. * * XXXX There is no reason to think that alternating is a particularly good * approach -- it's just designed to prevent destroys from starving other * cells completely. */ unsigned int last_cell_was_destroy : 1; /** Destroy counter: increment this when a destroy gets queued, decrement * when we unqueue it, so we can test to make sure they don't starve. */ int64_t destroy_ctr; /* * Circuitmux policy; if this is non-NULL, it can override the built- * in round-robin active circuits behavior. This is how EWMA works in * the new circuitmux_t world. */ const circuitmux_policy_t *policy; /* Policy-specific data */ circuitmux_policy_data_t *policy_data; }; /* * This struct holds whatever we want to store per attached circuit on a * circuitmux_t; right now, just the count of queued cells and the direction. Loading Loading @@ -221,9 +172,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a) ((unsigned int)(a->chan_id & 0xffffffff))); } /* Declare the struct chanid_circid_muxinfo_map type */ HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t); /* Emit a bunch of hash table stuff */ HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, chanid_circid_entry_hash, chanid_circid_entries_eq) Loading src/core/or/circuitmux.h +56 −0 Original line number Diff line number Diff line Loading @@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, MOCK_DECL(int, circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2)); #ifdef CIRCUITMUX_PRIVATE #include "core/or/destroy_cell_queue_st.h" /* * Map of muxinfos for circuitmux_t to use; struct is defined below (name * of struct must match HT_HEAD line). */ typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t) chanid_circid_muxinfo_map_t; /* * Structures for circuitmux.c */ struct circuitmux_s { /* Keep count of attached, active circuits */ unsigned int n_circuits, n_active_circuits; /* Total number of queued cells on all circuits */ unsigned int n_cells; /* * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t */ chanid_circid_muxinfo_map_t *chanid_circid_map; /** List of queued destroy cells */ destroy_cell_queue_t destroy_cell_queue; /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit * returned the destroy queue. Used to force alternation between * destroy/non-destroy cells. * * XXXX There is no reason to think that alternating is a particularly good * approach -- it's just designed to prevent destroys from starving other * cells completely. */ unsigned int last_cell_was_destroy : 1; /** Destroy counter: increment this when a destroy gets queued, decrement * when we unqueue it, so we can test to make sure they don't starve. */ int64_t destroy_ctr; /* * Circuitmux policy; if this is non-NULL, it can override the built- * in round-robin active circuits behavior. This is how EWMA works in * the new circuitmux_t world. */ const circuitmux_policy_t *policy; /* Policy-specific data */ circuitmux_policy_data_t *policy_data; }; #endif /* CIRCUITMUX_PRIVATE */ #endif /* !defined(TOR_CIRCUITMUX_H) */ src/core/or/circuitmux_ewma.c +0 −109 Original line number Diff line number Diff line Loading @@ -58,115 +58,6 @@ /** The natural logarithm of 0.5. */ #define LOG_ONEHALF -0.69314718055994529 /*** EWMA structures ***/ typedef struct cell_ewma_s cell_ewma_t; typedef struct ewma_policy_data_s ewma_policy_data_t; typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; /** * The cell_ewma_t structure keeps track of how many cells a circuit has * transferred recently. It keeps an EWMA (exponentially weighted moving * average) of the number of cells flushed from the circuit queue onto a * connection in channel_flush_from_first_active_circuit(). */ struct cell_ewma_s { /** The last 'tick' at which we recalibrated cell_count. * * A cell sent at exactly the start of this tick has weight 1.0. Cells sent * since the start of this tick have weight greater than 1.0; ones sent * earlier have less weight. */ unsigned int last_adjusted_tick; /** The EWMA of the cell count. */ double cell_count; /** True iff this is the cell count for a circuit's previous * channel. */ unsigned int is_for_p_chan : 1; /** The position of the circuit within the OR connection's priority * queue. */ int heap_index; }; struct ewma_policy_data_s { circuitmux_policy_data_t base_; /** * Priority queue of cell_ewma_t for circuits with queued cells waiting * for room to free up on the channel that owns this circuitmux. Kept * in heap order according to EWMA. This was formerly in channel_t, and * in or_connection_t before that. */ smartlist_t *active_circuit_pqueue; /** * The tick on which the cell_ewma_ts in active_circuit_pqueue last had * their ewma values rescaled. This was formerly in channel_t, and in * or_connection_t before that. */ unsigned int active_circuit_pqueue_last_recalibrated; }; struct ewma_policy_circ_data_s { circuitmux_policy_circ_data_t base_; /** * The EWMA count for the number of cells flushed from this circuit * onto this circuitmux. Used to determine which circuit to flush * from next. This was formerly in circuit_t and or_circuit_t. */ cell_ewma_t cell_ewma; /** * Pointer back to the circuit_t this is for; since we're separating * out circuit selection policy like this, we can't attach cell_ewma_t * to the circuit_t any more, so we can't use SUBTYPE_P directly to a * circuit_t like before; instead get it here. */ circuit_t *circ; }; #define EWMA_POL_DATA_MAGIC 0x2fd8b16aU #define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U /*** Downcasts for the above types ***/ static ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *); static ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *); /** * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert * if the cast is impossible. */ static inline ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); return DOWNCAST(ewma_policy_data_t, pol); } } /** * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t * and assert if the cast is impossible. */ static inline ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); return DOWNCAST(ewma_policy_circ_data_t, pol); } } /*** Static declarations for circuitmux_ewma.c ***/ static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma); Loading src/core/or/circuitmux_ewma.h +106 −1 Original line number Diff line number Diff line Loading @@ -22,9 +22,114 @@ void cmux_ewma_set_options(const or_options_t *options, void circuitmux_ewma_free_all(void); #ifdef CIRCUITMUX_EWMA_PRIVATE /*** EWMA structures ***/ typedef struct cell_ewma_s cell_ewma_t; typedef struct ewma_policy_data_s ewma_policy_data_t; typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; /** * The cell_ewma_t structure keeps track of how many cells a circuit has * transferred recently. It keeps an EWMA (exponentially weighted moving * average) of the number of cells flushed from the circuit queue onto a * connection in channel_flush_from_first_active_circuit(). */ struct cell_ewma_s { /** The last 'tick' at which we recalibrated cell_count. * * A cell sent at exactly the start of this tick has weight 1.0. Cells sent * since the start of this tick have weight greater than 1.0; ones sent * earlier have less weight. */ unsigned int last_adjusted_tick; /** The EWMA of the cell count. */ double cell_count; /** True iff this is the cell count for a circuit's previous * channel. */ unsigned int is_for_p_chan : 1; /** The position of the circuit within the OR connection's priority * queue. */ int heap_index; }; struct ewma_policy_data_s { circuitmux_policy_data_t base_; /** * Priority queue of cell_ewma_t for circuits with queued cells waiting * for room to free up on the channel that owns this circuitmux. Kept * in heap order according to EWMA. This was formerly in channel_t, and * in or_connection_t before that. */ smartlist_t *active_circuit_pqueue; /** * The tick on which the cell_ewma_ts in active_circuit_pqueue last had * their ewma values rescaled. This was formerly in channel_t, and in * or_connection_t before that. */ unsigned int active_circuit_pqueue_last_recalibrated; }; struct ewma_policy_circ_data_s { circuitmux_policy_circ_data_t base_; /** * The EWMA count for the number of cells flushed from this circuit * onto this circuitmux. Used to determine which circuit to flush * from next. This was formerly in circuit_t and or_circuit_t. */ cell_ewma_t cell_ewma; /** * Pointer back to the circuit_t this is for; since we're separating * out circuit selection policy like this, we can't attach cell_ewma_t * to the circuit_t any more, so we can't use SUBTYPE_P directly to a * circuit_t like before; instead get it here. */ circuit_t *circ; }; #define EWMA_POL_DATA_MAGIC 0x2fd8b16aU #define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U /*** Downcasts for the above types ***/ /** * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert * if the cast is impossible. */ static inline ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); return DOWNCAST(ewma_policy_data_t, pol); } } /** * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t * and assert if the cast is impossible. */ static inline ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); return DOWNCAST(ewma_policy_circ_data_t, pol); } } STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out); STATIC void cell_ewma_initialize_ticks(void); #endif #endif /* CIRCUITMUX_EWMA_PRIVATE */ #endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */ Loading
changes/ticket32196 0 → 100644 +2 −0 Original line number Diff line number Diff line o Testing (circuit, EWMA): - Add unit tests for circuitmux and EWMA subsystems. Closes ticket 32196.
src/core/or/circuitmux.c +2 −54 Original line number Diff line number Diff line Loading @@ -69,26 +69,20 @@ * made to attach all existing circuits to the new policy. **/ #define CIRCUITMUX_PRIVATE #include "core/or/or.h" #include "core/or/channel.h" #include "core/or/circuitlist.h" #include "core/or/circuitmux.h" #include "core/or/relay.h" #include "core/or/cell_queue_st.h" #include "core/or/destroy_cell_queue_st.h" #include "core/or/or_circuit_st.h" /* * Private typedefs for circuitmux.c */ /* * Map of muxinfos for circuitmux_t to use; struct is defined below (name * of struct must match HT_HEAD line). */ typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t; /* * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to * break the hash table code). Loading @@ -102,49 +96,6 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t; typedef struct circuit_muxinfo_s circuit_muxinfo_t; /* * Structures for circuitmux.c */ struct circuitmux_s { /* Keep count of attached, active circuits */ unsigned int n_circuits, n_active_circuits; /* Total number of queued cells on all circuits */ unsigned int n_cells; /* * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t */ chanid_circid_muxinfo_map_t *chanid_circid_map; /** List of queued destroy cells */ destroy_cell_queue_t destroy_cell_queue; /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit * returned the destroy queue. Used to force alternation between * destroy/non-destroy cells. * * XXXX There is no reason to think that alternating is a particularly good * approach -- it's just designed to prevent destroys from starving other * cells completely. */ unsigned int last_cell_was_destroy : 1; /** Destroy counter: increment this when a destroy gets queued, decrement * when we unqueue it, so we can test to make sure they don't starve. */ int64_t destroy_ctr; /* * Circuitmux policy; if this is non-NULL, it can override the built- * in round-robin active circuits behavior. This is how EWMA works in * the new circuitmux_t world. */ const circuitmux_policy_t *policy; /* Policy-specific data */ circuitmux_policy_data_t *policy_data; }; /* * This struct holds whatever we want to store per attached circuit on a * circuitmux_t; right now, just the count of queued cells and the direction. Loading Loading @@ -221,9 +172,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a) ((unsigned int)(a->chan_id & 0xffffffff))); } /* Declare the struct chanid_circid_muxinfo_map type */ HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t); /* Emit a bunch of hash table stuff */ HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, chanid_circid_entry_hash, chanid_circid_entries_eq) Loading
src/core/or/circuitmux.h +56 −0 Original line number Diff line number Diff line Loading @@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, MOCK_DECL(int, circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2)); #ifdef CIRCUITMUX_PRIVATE #include "core/or/destroy_cell_queue_st.h" /* * Map of muxinfos for circuitmux_t to use; struct is defined below (name * of struct must match HT_HEAD line). */ typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t) chanid_circid_muxinfo_map_t; /* * Structures for circuitmux.c */ struct circuitmux_s { /* Keep count of attached, active circuits */ unsigned int n_circuits, n_active_circuits; /* Total number of queued cells on all circuits */ unsigned int n_cells; /* * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t */ chanid_circid_muxinfo_map_t *chanid_circid_map; /** List of queued destroy cells */ destroy_cell_queue_t destroy_cell_queue; /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit * returned the destroy queue. Used to force alternation between * destroy/non-destroy cells. * * XXXX There is no reason to think that alternating is a particularly good * approach -- it's just designed to prevent destroys from starving other * cells completely. */ unsigned int last_cell_was_destroy : 1; /** Destroy counter: increment this when a destroy gets queued, decrement * when we unqueue it, so we can test to make sure they don't starve. */ int64_t destroy_ctr; /* * Circuitmux policy; if this is non-NULL, it can override the built- * in round-robin active circuits behavior. This is how EWMA works in * the new circuitmux_t world. */ const circuitmux_policy_t *policy; /* Policy-specific data */ circuitmux_policy_data_t *policy_data; }; #endif /* CIRCUITMUX_PRIVATE */ #endif /* !defined(TOR_CIRCUITMUX_H) */
src/core/or/circuitmux_ewma.c +0 −109 Original line number Diff line number Diff line Loading @@ -58,115 +58,6 @@ /** The natural logarithm of 0.5. */ #define LOG_ONEHALF -0.69314718055994529 /*** EWMA structures ***/ typedef struct cell_ewma_s cell_ewma_t; typedef struct ewma_policy_data_s ewma_policy_data_t; typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; /** * The cell_ewma_t structure keeps track of how many cells a circuit has * transferred recently. It keeps an EWMA (exponentially weighted moving * average) of the number of cells flushed from the circuit queue onto a * connection in channel_flush_from_first_active_circuit(). */ struct cell_ewma_s { /** The last 'tick' at which we recalibrated cell_count. * * A cell sent at exactly the start of this tick has weight 1.0. Cells sent * since the start of this tick have weight greater than 1.0; ones sent * earlier have less weight. */ unsigned int last_adjusted_tick; /** The EWMA of the cell count. */ double cell_count; /** True iff this is the cell count for a circuit's previous * channel. */ unsigned int is_for_p_chan : 1; /** The position of the circuit within the OR connection's priority * queue. */ int heap_index; }; struct ewma_policy_data_s { circuitmux_policy_data_t base_; /** * Priority queue of cell_ewma_t for circuits with queued cells waiting * for room to free up on the channel that owns this circuitmux. Kept * in heap order according to EWMA. This was formerly in channel_t, and * in or_connection_t before that. */ smartlist_t *active_circuit_pqueue; /** * The tick on which the cell_ewma_ts in active_circuit_pqueue last had * their ewma values rescaled. This was formerly in channel_t, and in * or_connection_t before that. */ unsigned int active_circuit_pqueue_last_recalibrated; }; struct ewma_policy_circ_data_s { circuitmux_policy_circ_data_t base_; /** * The EWMA count for the number of cells flushed from this circuit * onto this circuitmux. Used to determine which circuit to flush * from next. This was formerly in circuit_t and or_circuit_t. */ cell_ewma_t cell_ewma; /** * Pointer back to the circuit_t this is for; since we're separating * out circuit selection policy like this, we can't attach cell_ewma_t * to the circuit_t any more, so we can't use SUBTYPE_P directly to a * circuit_t like before; instead get it here. */ circuit_t *circ; }; #define EWMA_POL_DATA_MAGIC 0x2fd8b16aU #define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U /*** Downcasts for the above types ***/ static ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *); static ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *); /** * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert * if the cast is impossible. */ static inline ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); return DOWNCAST(ewma_policy_data_t, pol); } } /** * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t * and assert if the cast is impossible. */ static inline ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); return DOWNCAST(ewma_policy_circ_data_t, pol); } } /*** Static declarations for circuitmux_ewma.c ***/ static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma); Loading
src/core/or/circuitmux_ewma.h +106 −1 Original line number Diff line number Diff line Loading @@ -22,9 +22,114 @@ void cmux_ewma_set_options(const or_options_t *options, void circuitmux_ewma_free_all(void); #ifdef CIRCUITMUX_EWMA_PRIVATE /*** EWMA structures ***/ typedef struct cell_ewma_s cell_ewma_t; typedef struct ewma_policy_data_s ewma_policy_data_t; typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; /** * The cell_ewma_t structure keeps track of how many cells a circuit has * transferred recently. It keeps an EWMA (exponentially weighted moving * average) of the number of cells flushed from the circuit queue onto a * connection in channel_flush_from_first_active_circuit(). */ struct cell_ewma_s { /** The last 'tick' at which we recalibrated cell_count. * * A cell sent at exactly the start of this tick has weight 1.0. Cells sent * since the start of this tick have weight greater than 1.0; ones sent * earlier have less weight. */ unsigned int last_adjusted_tick; /** The EWMA of the cell count. */ double cell_count; /** True iff this is the cell count for a circuit's previous * channel. */ unsigned int is_for_p_chan : 1; /** The position of the circuit within the OR connection's priority * queue. */ int heap_index; }; struct ewma_policy_data_s { circuitmux_policy_data_t base_; /** * Priority queue of cell_ewma_t for circuits with queued cells waiting * for room to free up on the channel that owns this circuitmux. Kept * in heap order according to EWMA. This was formerly in channel_t, and * in or_connection_t before that. */ smartlist_t *active_circuit_pqueue; /** * The tick on which the cell_ewma_ts in active_circuit_pqueue last had * their ewma values rescaled. This was formerly in channel_t, and in * or_connection_t before that. */ unsigned int active_circuit_pqueue_last_recalibrated; }; struct ewma_policy_circ_data_s { circuitmux_policy_circ_data_t base_; /** * The EWMA count for the number of cells flushed from this circuit * onto this circuitmux. Used to determine which circuit to flush * from next. This was formerly in circuit_t and or_circuit_t. */ cell_ewma_t cell_ewma; /** * Pointer back to the circuit_t this is for; since we're separating * out circuit selection policy like this, we can't attach cell_ewma_t * to the circuit_t any more, so we can't use SUBTYPE_P directly to a * circuit_t like before; instead get it here. */ circuit_t *circ; }; #define EWMA_POL_DATA_MAGIC 0x2fd8b16aU #define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U /*** Downcasts for the above types ***/ /** * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert * if the cast is impossible. */ static inline ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); return DOWNCAST(ewma_policy_data_t, pol); } } /** * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t * and assert if the cast is impossible. */ static inline ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) { if (!pol) return NULL; else { tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); return DOWNCAST(ewma_policy_circ_data_t, pol); } } STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out); STATIC void cell_ewma_initialize_ticks(void); #endif #endif /* CIRCUITMUX_EWMA_PRIVATE */ #endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */