27 #if LOG2_TW_TIMERS_PER_OBJECT > 0 41 TWT (tw_timer) * old_first;
49 head->next = head->prev = new_index;
50 new->next =
new->prev = head_index;
54 old_first_index = head->next;
57 new->next = old_first_index;
58 new->prev = old_first->prev;
59 old_first->prev = new_index;
60 head->next = new_index;
67 TWT (tw_timer) * next_elt, *prev_elt;
69 ASSERT (elt->user_handle != ~0);
74 next_elt->prev = elt->prev;
75 prev_elt->next = elt->next;
77 elt->prev = elt->next = ~0;
92 #if TW_TIMER_WHEELS > 1 96 #if TW_TIMER_WHEELS > 2 97 u16 glacier_ring_offset;
99 #if TW_OVERFLOW_VECTOR > 0 100 u64 interval_plus_time_to_wrap, triple_wrap_mask;
102 u16 fast_ring_offset;
109 memset (t, 0xff,
sizeof (*t));
114 #if TW_TIMER_WHEELS > 2 115 #if TW_OVERFLOW_VECTOR > 0 123 interval_plus_time_to_wrap =
124 interval + (tw->current_tick & triple_wrap_mask);
125 if ((interval_plus_time_to_wrap >= 1 << (3 *
TW_RING_SHIFT)))
127 t->expiration_time = tw->current_tick + interval;
130 return t - tw->timers;
138 #if TW_TIMER_WHEELS > 1 154 #if TW_TIMER_WHEELS > 1 163 #if TW_TIMER_WHEELS > 2 164 glacier_ring_offset +=
169 #if TW_TIMER_WHEELS > 2 170 if (glacier_ring_offset !=
174 t->slow_ring_offset = slow_ring_offset;
175 t->fast_ring_offset = fast_ring_offset;
181 return t - tw->timers;
185 #if TW_TIMER_WHEELS > 1 187 if (slow_ring_offset !=
191 t->fast_ring_offset = fast_ring_offset;
197 return t - tw->timers;
207 return t - tw->timers;
210 #if TW_TIMER_SCAN_FOR_HANDLE > 0 211 int TW (scan_for_handle) (
TWT (tw_timer_wheel) * tw,
u32 handle)
215 TWT (tw_timer) * t, *head;
225 next_index = head->next;
230 if (next_index == handle)
237 next_index = t->next;
257 ASSERT (t->user_handle != ~0);
273 void *expired_timer_callback,
274 f64 timer_interval_in_seconds,
u32 max_expirations)
279 memset (tw, 0,
sizeof (*tw));
280 tw->expired_timer_callback = expired_timer_callback;
281 tw->max_expirations = max_expirations;
282 if (timer_interval_in_seconds == 0.0)
287 tw->timer_interval = timer_interval_in_seconds;
288 tw->ticks_per_second = 1.0 / timer_interval_in_seconds;
289 tw->first_expires_tick = ~0ULL;
291 _vec_len (tw->expired_timer_handles) = 0;
297 ts = &tw->w[ring][slot];
299 memset (t, 0xff,
sizeof (*t));
300 t->next = t->prev = t - tw->timers;
305 #if TW_OVERFLOW_VECTOR > 0 308 memset (t, 0xff,
sizeof (*t));
309 t->next = t->prev = t - tw->timers;
322 TWT (tw_timer) * head, *t;
331 next_index = head->next;
336 next_index = t->next;
343 #if TW_OVERFLOW_VECVOR > 0 346 next_index = head->next;
351 next_index = t->next;
357 memset (tw, 0,
sizeof (*tw));
370 u32 * callback_vector_arg)
374 TWT (tw_timer) * t, *head;
375 u32 *callback_vector;
376 u32 fast_wheel_index;
378 u32 slow_wheel_index __attribute__ ((unused));
379 u32 glacier_wheel_index __attribute__ ((unused));
383 return callback_vector_arg;
386 nticks = tw->ticks_per_second * (now - tw->last_run_time);
388 return callback_vector_arg;
391 tw->next_run_time = (now + tw->timer_interval);
393 if (callback_vector_arg == 0)
395 _vec_len (tw->expired_timer_handles) = 0;
396 callback_vector = tw->expired_timer_handles;
399 callback_vector = callback_vector_arg;
401 for (i = 0; i < nticks; i++)
409 #if TW_OVERFLOW_VECTOR > 0 416 u32 new_glacier_ring_offset, new_slow_ring_offset;
417 u32 new_fast_ring_offset;
421 next_index = head->next;
427 while (next_index != head - tw->timers)
430 next_index = t->next;
433 t->next = t->prev = ~0;
435 ASSERT (t->expiration_time >= tw->current_tick);
437 interval = t->expiration_time - tw->current_tick;
449 interval -= (new_glacier_ring_offset << (2 *
TW_RING_SHIFT));
455 t->slow_ring_offset = new_slow_ring_offset;
456 t->fast_ring_offset = new_fast_ring_offset;
460 t->fast_ring_offset == 0 &&
461 new_glacier_ring_offset == 0))
463 vec_add1 (callback_vector, t->user_handle);
467 else if (new_glacier_ring_offset)
473 else if (t->slow_ring_offset)
489 #if TW_TIMER_WHEELS > 2 500 next_index = head->next;
506 while (next_index != head - tw->timers)
509 next_index = t->next;
512 t->next = t->prev = ~0;
516 t->fast_ring_offset == 0))
518 vec_add1 (callback_vector, t->user_handle);
537 #if TW_TIMER_WHEELS > 1 547 next_index = head->next;
553 while (next_index != head - tw->timers)
556 next_index = t->next;
559 t->next = t->prev = ~0;
564 vec_add1 (callback_vector, t->user_handle);
582 next_index = head->next;
591 next_index = t->next;
592 vec_add1 (callback_vector, t->user_handle);
597 if (callback_vector_arg == 0 &&
vec_len (callback_vector))
600 if (tw->expired_timer_callback)
602 tw->expired_timer_callback (callback_vector);
603 _vec_len (callback_vector) = 0;
605 tw->expired_timer_handles = callback_vector;
611 #if TW_TIMER_WHEELS > 1 617 #if TW_TIMER_WHEELS > 2 619 glacier_wheel_index++;
623 if (
vec_len (callback_vector) >= tw->max_expirations)
627 if (callback_vector_arg == 0)
628 tw->expired_timer_handles = callback_vector;
630 tw->last_run_time += i * tw->timer_interval;
631 return callback_vector;
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void TW() tw_timer_wheel_init(TWT(tw_timer_wheel)*tw, void *expired_timer_callback, f64 timer_interval_in_seconds, u32 max_expirations)
Initialize a tw timer wheel template instance.
sll srl srl sll sra u16x4 i
#define TW_TIMERS_PER_OBJECT
u32 *TW() tw_timer_expire_timers_vec(TWT(tw_timer_wheel)*tw, f64 now, u32 *vec)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
#define LOG2_TW_TIMERS_PER_OBJECT
u32 TW() tw_timer_start(TWT(tw_timer_wheel)*tw, u32 pool_index, u32 timer_id, u64 interval)
Start a Tw Timer.
static void timer_addhead(TWT(tw_timer)*pool, u32 head_index, u32 new_index)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
#define TW_SLOTS_PER_RING
static u32 *TW() tw_timer_expire_timers_internal(TWT(tw_timer_wheel)*tw, f64 now, u32 *callback_vector_arg)
Advance a tw timer wheel.
#define pool_put(P, E)
Free an object E in pool P.
#define clib_warning(format, args...)
void TW() tw_timer_stop(TWT(tw_timer_wheel)*tw, u32 handle)
Stop a tw timer.
static void timer_remove(TWT(tw_timer)*pool, u32 index)
u32 *TW() tw_timer_expire_timers(TWT(tw_timer_wheel)*tw, f64 now)
#define pool_put_index(p, i)
Free pool element with given index.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static u32 TW() make_internal_timer_handle(u32 pool_index, u32 timer_id)
void TW() tw_timer_wheel_free(TWT(tw_timer_wheel)*tw)
Free a tw timer wheel template instance.
u32 head_index
Listhead of timers which expire in this interval.