67 ASSERT (rtime < w->bins_per_wheel);
68 *rtime_result = rtime;
103 error = CLIB_ERROR_ASSERT (x); \ 105 if (error) return error; \ 120 uword e_ti, e_li, e_wi;
126 if (e_li == level_index - 1)
133 _ (e_li == level_index);
137 _ (e_wi == wi || e_wi + 1 == wi || e_wi - 1 == wi);
170 memset (ev, ~0,
vec_len (ev) *
sizeof (ev[0]));
214 uword rtime, level_index;
285 l->elts[wi] = delete_user_data (l->elts[wi], user_data);
286 if (vec_len (l->elts[wi]) == 0)
287 l->occupancy_bitmap = clib_bitmap_andnoti (l->occupancy_bitmap, wi);
294 if (oe->user_data == user_data)
295 pool_put (w->overflow_pool, oe);
359 wrapped = wi != wi + 1;
370 ({ min_t = clib_min (min_t, oe->cpu_time); }));
390 u64 current_cpu_time)
406 u64 advance_cpu_time,
407 u32 * expired_user_data)
417 vec_add2 (expired_user_data, x, e_len);
418 for (i = j = 0; i < e_len; i++)
429 _vec_len (expired_user_data) -= e_len - j;
433 level->
elts[wheel_index] = 0;
436 return expired_user_data;
456 vec_foreach (e, l->elts[wi])
460 ASSERT (e->cpu_time_relative_to_base >= delta);
461 e->cpu_time_relative_to_base -= delta;
471 if (0 == ((oe->cpu_time - w->cpu_time_base) >> BITS (e->cpu_time_relative_to_base)))
473 u64 ti = oe->cpu_time >> w->log2_clocks_per_bin;
474 if (ti < w->current_time_index)
478 if (! elt_is_deleted (w, oe->user_data))
479 vec_add1 (expired_user_data, oe->user_data);
482 timing_wheel_insert_helper (w, oe->cpu_time, oe->user_data);
483 pool_put (w->overflow_pool, oe);
492 u64 advance_cpu_time,
493 uword from_wheel_index,
494 uword to_wheel_index,
495 u32 * expired_user_data)
517 es = level->
elts[from_wheel_index];
518 level->
elts[from_wheel_index] = 0;
525 if (ti <= advance_time_index)
537 if (from_wheel_index == to_wheel_index)
540 from_wheel_index =
wheel_add (w, from_wheel_index + 1);
546 return expired_user_data;
552 u64 * next_expiring_element_cpu_time)
555 uword level_index, advance_rtime, advance_level_index, advance_wheel_index;
556 uword n_expired_user_data_before;
557 u64 current_time_index, advance_time_index;
559 n_expired_user_data_before =
vec_len (expired_user_data);
566 u64 current_ti, advance_ti;
577 while (current_ti != advance_ti)
599 for (level_index = 0; level_index < advance_level_index; level_index++)
608 expired_user_data = expire_bin (w, level_index, wi, advance_cpu_time,
622 expired_user_data =
expire_bin (w, advance_level_index, wi, advance_cpu_time,
625 if (wi == advance_wheel_index)
647 if (next_expiring_element_cpu_time)
652 if (
vec_len (expired_user_data) == n_expired_user_data_before
661 *next_expiring_element_cpu_time = min_t;
664 return expired_user_data;
670 int verbose = va_arg (*va,
int);
673 s =
format (s,
"level 0: %.4e - %.4e secs, 2^%d - 2^%d clocks",
682 s =
format (s,
"\n%Utime base advances %Ld, every %.4e secs",
688 s =
format (s,
"\n%Ulevel %d: refills %Ld",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
timing_wheel_overflow_elt_t * overflow_pool
void timing_wheel_validate(timing_wheel_t *w)
sll srl srl sll sra u16x4 i
static void advance_cpu_time_base(timing_wheel_t *w, u32 *expired_user_data)
always_inline void validate_expired_elt(timing_wheel_t *w, timing_wheel_elt_t *e, u64 current_cpu_time)
#define hash_unset(h, key)
#define STRUCT_BITS_OF(t, f)
void timing_wheel_init(timing_wheel_t *w, u64 current_cpu_time, f64 cpu_clocks_per_second)
u64 timing_wheel_next_expiring_elt_time(timing_wheel_t *w)
u64 cached_min_cpu_time_on_wheel
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
always_inline uword max_log2(uword x)
always_inline uword time_index_to_wheel_index(timing_wheel_t *w, uword level_index, u64 ti)
#define clib_error_report(e)
void timing_wheel_insert(timing_wheel_t *w, u64 insert_cpu_time, u32 user_data)
#define vec_pop(V)
Returns last element of a vector and decrements its length.
always_inline void free_elt_vector(timing_wheel_t *w, timing_wheel_elt_t *ev)
static timing_wheel_elt_t * delete_user_data(timing_wheel_elt_t *elts, u32 user_data)
#define clib_bitmap_validate(v, n_bits)
static timing_wheel_elt_t * insert_helper(timing_wheel_t *w, uword level_index, uword rtime)
#define pool_foreach(VAR, POOL, BODY)
always_inline uword wheel_add(timing_wheel_t *w, word x)
timing_wheel_stats_t stats
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
f64 cpu_clocks_per_second
always_inline uword pool_elts(void *v)
static u32 * expire_bin(timing_wheel_t *w, uword level_index, uword wheel_index, u64 advance_cpu_time, u32 *expired_user_data)
#define clib_bitmap_foreach(i, ai, body)
always_inline uword clib_bitmap_set_no_check(uword *a, uword i, uword new_value)
timing_wheel_elt_t ** free_elt_vectors
always_inline uword get_level_and_relative_time(timing_wheel_t *w, u64 cpu_time, uword *rtime_result)
u8 * format_timing_wheel(u8 *s, va_list *va)
static void timing_wheel_insert_helper(timing_wheel_t *w, u64 insert_cpu_time, u32 user_data)
#define vec_free(V)
Free vector's memory (no header).
u32 * timing_wheel_advance(timing_wheel_t *w, u64 advance_cpu_time, u32 *expired_user_data, u64 *next_expiring_element_cpu_time)
void timing_wheel_delete(timing_wheel_t *w, u32 user_data)
always_inline uword hash_elts(void *v)
always_inline u64 elt_cpu_time(timing_wheel_t *w, timing_wheel_elt_t *e)
timing_wheel_elt_t ** elts
#define hash_set1(h, key)
timing_wheel_elt_t * unexpired_elts_pending_insert
#define hash_create(elts, value_bytes)
uword * deleted_user_data_hash
u64 time_index_next_cpu_time_base_update
always_inline uword elt_is_deleted(timing_wheel_t *w, u32 user_data)
timing_wheel_level_t * levels
#define vec_elt(v, i)
Get vector value at index i.
always_inline uword current_time_wheel_index(timing_wheel_t *w, uword level_index)
always_inline uword clib_bitmap_get_no_check(uword *ai, uword i)
always_inline uword rtime_to_wheel_index(timing_wheel_t *w, uword level_index, uword rtime)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static u32 * refill_level(timing_wheel_t *w, uword level_index, u64 advance_cpu_time, uword from_wheel_index, uword to_wheel_index, u32 *expired_user_data)
#define vec_foreach(var, vec)
Vector iterator.
static void insert_elt(timing_wheel_t *w, timing_wheel_elt_t *e)
u64 cpu_time_base_advances
static clib_error_t * validate_level(timing_wheel_t *w, uword level_index, uword *n_elts)
u32 cpu_time_relative_to_base