#include #include #include #include #include #include #include #include typedef struct { /** Handle returned from tw_start_timer */ u32 stop_timer_handle; /** Test item should expire at this clock tick */ u64 expected_to_expire; } tw_timer_test_elt_t; typedef struct { /** Pool of test objects */ tw_timer_test_elt_t *test_elts; /** The single-wheel */ tw_timer_wheel_2t_1w_2048sl_t single_wheel; /** The double-wheel */ tw_timer_wheel_16t_2w_512sl_t double_wheel; /* The triple wheel */ tw_timer_wheel_4t_3w_256sl_t triple_wheel; /* The triple wheel with overflow vector */ tw_timer_wheel_1t_3w_1024sl_ov_t triple_ov_wheel; /* Another two timer wheel geometry */ tw_timer_wheel_2t_2w_512sl_t two_timer_double_wheel; /** random number seed */ u64 seed; /** number of timers */ u32 ntimers; /** number of "churn" iterations */ u32 niter; /** number of clock ticks per churn iteration */ u32 ticks_per_iter; /** cpu timer */ clib_time_t clib_time; } tw_timer_test_main_t; tw_timer_test_main_t tw_timer_test_main; static void run_single_wheel (tw_timer_wheel_2t_1w_2048sl_t * tw, u32 n_ticks) { u32 i; f64 now = tw->last_run_time + 1.01; for (i = 0; i < n_ticks; i++) { tw_timer_expire_timers_2t_1w_2048sl (tw, now); now += 1.01; } } static void run_double_wheel (tw_timer_wheel_16t_2w_512sl_t * tw, u32 n_ticks) { u32 i; f64 now = tw->last_run_time + 1.01; for (i = 0; i < n_ticks; i++) { tw_timer_expire_timers_16t_2w_512sl (tw, now); now += 1.01; } } static void run_two_timer_double_wheel (tw_timer_wheel_2t_2w_512sl_t * tw, u32 n_ticks) { u32 i; f64 now = tw->last_run_time + 1.01; for (i = 0; i < n_ticks; i++) { tw_timer_expire_timers_2t_2w_512sl (tw, now); now += 1.01; } } static void run_triple_wheel (tw_timer_wheel_4t_3w_256sl_t * tw, u32 n_ticks) { u32 i; f64 now = tw->last_run_time + 1.01; for (i = 0; i < n_ticks; i++) { tw_timer_expire_timers_4t_3w_256sl (tw, now); now += 1.01; } } static void run_triple_ov_wheel (tw_timer_wheel_1t_3w_1024sl_ov_t * tw, u32 n_ticks) { u32 i; f64 now = tw->last_run_time + 1.01; for (i = 0; i < n_ticks; i++) { tw_timer_expire_timers_1t_3w_1024sl_ov (tw, now); now += 1.01; } } static void expired_timer_single_callback (u32 * expired_timers) { int i; u32 pool_index, timer_id; tw_timer_test_elt_t *e; tw_timer_test_main_t *tm = &tw_timer_test_main; for (i = 0; i < vec_len (expired_timers); i++) { pool_index = expired_timers[i] & 0x7FFFFFFF; timer_id = expired_timers[i] >> 31; ASSERT (timer_id == 1); e = pool_elt_at_index (tm->test_elts, pool_index); if (e->expected_to_expire != tm->single_wheel.current_tick) { fformat (stdout, "[%d] expired at %lld not %lld\n", e - tm->test_elts, tm->single_wheel.current_tick, e->expected_to_expire); } pool_put (tm->test_elts, e); } } static void expired_timer_double_callback (u32 * expired_timers) { int i; u32 pool_index, timer_id; tw_timer_test_elt_t *e; tw_timer_test_main_t *tm = &tw_timer_test_main; for (i = 0; i < vec_len (expired_timers); i++) { pool_index = expired_timers[i] & 0x0FFFFFFF; timer_id = expired_timers[i] >> 28; ASSERT (timer_id == 14); e = pool_elt_at_index (tm->test_elts, pool_index); if (e->expected_to_expire != tm->double_wheel.current_tick) { fformat (stdout, "[%d] expired at %lld not %lld\n", e - tm->test_elts, tm->double_wheel.current_tick, e->expected_to_expire); } pool_put (tm->test_elts, e); } } static void expired_timer_two_timer_double_callback (u32 * expired_timers) { int i; u32 pool_index, timer_id; tw_timer_test_elt_t *e; tw_timer_test_main_t *tm = &tw_timer_test_main; for (i = 0; i < vec_len (expired_timers); i++) { pool_index = expired_timers[i] & 0x7FFFFFFF; timer_id = expired_timers[i] >> 31; ASSERT (timer_id == 1); e = pool_elt_at_index (tm->test_elts, pool_index); if (e->expected_to_expire != tm->two_timer_double_wheel.current_tick) { fformat (stdout, "[%d] expired at %lld not %lld\n", e - tm->test_elts, tm->two_timer_double_wheel.current_tick, e->expected_to_expire); } pool_put (tm->test_elts, e); } } static void expired_timer_triple_callback (u32 * expired_timers) { int i; u32 pool_index, timer_id; tw_timer_test_elt_t *e; tw_timer_test_main_t *tm = &tw_timer_test_main; for (i = 0; i < vec_len (expired_timers); i++) { pool_index = expired_timers[i] & 0x3FFFFFFF; timer_id = expired_timers[i] >> 30; ASSERT (timer_id == 3); e = pool_elt_at_index (tm->test_elts, pool_index); if (e->expected_to_expire != tm->triple_wheel.current_tick) { fformat (stdout, "[%d] expired at %lld not %lld\n", e - tm->test_elts, tm->triple_wheel.current_tick, e->expected_to_expire); } pool_put (tm->test_elts, e); } } static void expired_timer_triple_ov_callback (u32 * expired_timers) { int i; u32 pool_index; tw_timer_test_elt_t *e; tw_timer_test_main_t *tm = &tw_timer_test_main; for (i = 0; i < vec_len (expired_timers); i++) { pool_index = expired_timers[i]; e = pool_elt_at_index (tm->test_elts, pool_index); if (e->expected_to_expire != tm->triple_ov_wheel.current_tick) { fformat (stdout, "[%d] expired at %lld not %lld\n", e - tm->test_elts, tm->triple_ov_wheel.current_tick, e->expected_to_expire); } pool_put (tm->test_elts, e); } } static clib_error_t * test2_single (tw_timer_test_main_t * tm) { u32 i, j; tw_timer_test_elt_t *e; u32 initial_wheel_offset; u64 expiration_time; u32 max_expiration_time = 0; u32 *deleted_indices = 0; u32 adds = 0, deletes = 0; f64 before, after; clib_time_init (&tm->clib_time); tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel, expired_timer_single_callback, 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 757; run_single_wheel (&tm->single_wheel, initial_wheel_offset); fformat (stdout, "initial wheel time %d, fast index %d\n", tm->single_wheel.current_tick, tm->single_wheel.current_index[TW_TIMER_RING_FAST]); initial_wheel_offset = tm->single_wheel.current_tick; fformat (stdout, "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n", tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed); before = clib_time_now (&tm->clib_time); /* Prime the pump */ for (i = 0; i < tm->ntimers; i++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & (2047); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + initial_wheel_offset; e->stop_timer_handle = tw_timer_start_2t_1w_2048sl (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ , expiration_time); } adds += i; for (i = 0; i < tm->niter; i++) { run_single_wheel (&tm->single_wheel, tm->ticks_per_iter); j = 0; vec_reset_length (deleted_indices); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { tw_timer_stop_2t_1w_2048sl (&tm->single_wheel, e->stop_timer_handle); vec_add1 (deleted_indices, e - tm->test_elts); if (++j >= tm->ntimers / 4) goto del_and_re_add; } /* *INDENT-ON* */ del_and_re_add: for (j = 0; j < vec_len (deleted_indices); j++) { pool_put_index (tm->test_elts, deleted_indices[j]); } deletes += j; for (j = 0; j < tm->ntimers / 4; j++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & (2047); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + tm->single_wheel.current_tick; e->stop_timer_handle = tw_timer_start_2t_1w_2048sl (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ , expiration_time); } adds += j; } vec_free (deleted_indices); run_single_wheel (&tm->single_wheel, max_expiration_time + 1); after = clib_time_now (&tm->clib_time); fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes, tm->single_wheel.current_tick); fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n", (after - before), ((f64) adds + (f64) deletes + (f64) tm->single_wheel.current_tick) / (after - before)); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { fformat (stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); } /* *INDENT-ON* */ pool_free (tm->test_elts); tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel); return 0; } static clib_error_t * test2_double (tw_timer_test_main_t * tm) { u32 i, j; tw_timer_test_elt_t *e; u32 initial_wheel_offset; u32 expiration_time; u32 max_expiration_time = 0; u32 *deleted_indices = 0; u32 adds = 0, deletes = 0; f64 before, after; clib_time_init (&tm->clib_time); tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel, expired_timer_double_callback, 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 7577; run_double_wheel (&tm->double_wheel, initial_wheel_offset); fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n", tm->double_wheel.current_tick, tm->double_wheel.current_index[TW_TIMER_RING_FAST], tm->double_wheel.current_index[TW_TIMER_RING_SLOW]); initial_wheel_offset = tm->double_wheel.current_tick; fformat (stdout, "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n", tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed); before = clib_time_now (&tm->clib_time); /* Prime the pump */ for (i = 0; i < tm->ntimers; i++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + initial_wheel_offset; e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ , expiration_time); } adds += i; for (i = 0; i < tm->niter; i++) { run_double_wheel (&tm->double_wheel, tm->ticks_per_iter); j = 0; vec_reset_length (deleted_indices); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { tw_timer_stop_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle); vec_add1 (deleted_indices, e - tm->test_elts); if (++j >= tm->ntimers / 4) goto del_and_re_add; } /* *INDENT-ON* */ del_and_re_add: for (j = 0; j < vec_len (deleted_indices); j++) pool_put_index (tm->test_elts, deleted_indices[j]); deletes += j; for (j = 0; j < tm->ntimers / 4; j++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + tm->double_wheel.current_tick; e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ , expiration_time); } adds += j; } vec_free (deleted_indices); run_double_wheel (&tm->double_wheel, max_expiration_time + 1); after = clib_time_now (&tm->clib_time); fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes, tm->double_wheel.current_tick); fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n", (after - before), ((f64) adds + (f64) deletes + (f64) tm->double_wheel.current_tick) / (after - before)); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { fformat (stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); } /* *INDENT-ON* */ pool_free (tm->test_elts); tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel); return 0; } static u32 get_expiration_time (tw_timer_test_main_t * tm) { u32 expiration_time; do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); return expiration_time; } static clib_error_t * test2_double_updates (tw_timer_test_main_t * tm) { u32 i, j; tw_timer_test_elt_t *e; u32 initial_wheel_offset; u32 expiration_time; u32 max_expiration_time = 0, updates = 0; f64 before, after; clib_time_init (&tm->clib_time); tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel, expired_timer_double_callback, 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 7577; run_double_wheel (&tm->double_wheel, initial_wheel_offset); fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n", tm->double_wheel.current_tick, tm->double_wheel.current_index[TW_TIMER_RING_FAST], tm->double_wheel.current_index[TW_TIMER_RING_SLOW]); initial_wheel_offset = tm->double_wheel.current_tick; fformat (stdout, "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n", tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed); before = clib_time_now (&tm->clib_time); /* Prime the pump */ for (i = 0; i < tm->ntimers; i++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); expiration_time = get_expiration_time (tm); max_expiration_time = clib_max (expiration_time, max_expiration_time); e->expected_to_expire = expiration_time + initial_wheel_offset; e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ , expiration_time); } for (i = 0; i < tm->niter; i++) { run_double_wheel (&tm->double_wheel, tm->ticks_per_iter); j = 0; /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { expiration_time = get_expiration_time (tm); max_expiration_time = clib_max (expiration_time, max_expiration_time); e->expected_to_expire = expiration_time + tm->double_wheel.current_tick; tw_timer_update_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle, expiration_time); if (++j >= tm->ntimers / 4) goto done; } /* *INDENT-ON* */ done: updates += j; } run_double_wheel (&tm->double_wheel, max_expiration_time + 1); after = clib_time_now (&tm->clib_time); fformat (stdout, "%d updates, %d ticks\n", updates, tm->double_wheel.current_tick); fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n", (after - before), ((f64) updates + (f64) tm->double_wheel.current_tick) / (after - before)); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { fformat (stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); } /* *INDENT-ON* */ pool_free (tm->test_elts); tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel); return 0; } static clib_error_t * test2_triple (tw_timer_test_main_t * tm) { u32 i, j; tw_timer_test_elt_t *e; u32 initial_wheel_offset = 0; u32 expiration_time; u32 max_expiration_time = 0; u32 *deleted_indices = 0; u32 adds = 0, deletes = 0; f64 before, after; clib_time_init (&tm->clib_time); tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel, expired_timer_triple_callback, 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 75700; run_triple_wheel (&tm->triple_wheel, initial_wheel_offset); fformat (stdout, "initial wheel time %d, fi %d si %d gi %d\n", tm->triple_wheel.current_tick, tm->triple_wheel.current_index[TW_TIMER_RING_FAST], tm->triple_wheel.current_index[TW_TIMER_RING_SLOW], tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]); initial_wheel_offset = tm->triple_wheel.current_tick; fformat (stdout, "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n", tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed); before = clib_time_now (&tm->clib_time); /* Prime the pump */ for (i = 0; i < tm->ntimers; i++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + initial_wheel_offset; e->stop_timer_handle = tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts, 3 /* timer id */ , expiration_time); } adds += i; for (i = 0; i < tm->niter; i++) { run_triple_wheel (&tm->triple_wheel, tm->ticks_per_iter); j = 0; vec_reset_length (deleted_indices); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { tw_timer_stop_4t_3w_256sl (&tm->triple_wheel, e->stop_timer_handle); vec_add1 (deleted_indices, e - tm->test_elts); if (++j >= tm->ntimers / 4) goto del_and_re_add; } /* *INDENT-ON* */ del_and_re_add: for (j = 0; j < vec_len (deleted_indices); j++) pool_put_index (tm->test_elts, deleted_indices[j]); deletes += j; for (j = 0; j < tm->ntimers / 4; j++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + tm->triple_wheel.current_tick; e->stop_timer_handle = tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts, 3 /* timer id */ , expiration_time); } adds += j; } vec_free (deleted_indices); run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1); after = clib_time_now (&tm->clib_time); fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes, tm->triple_wheel.current_tick); fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n", (after - before), ((f64) adds + (f64) deletes + (f64) tm->triple_wheel.current_tick) / (after - before)); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { fformat (stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); } /* *INDENT-ON* */ pool_free (tm->test_elts); tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel); return 0; } static clib_error_t * test2_triple_ov (tw_timer_test_main_t * tm) { u32 i, j; tw_timer_test_elt_t *e; u32 initial_wheel_offset = 0; u32 expiration_time; u32 max_expiration_time = 0; u32 *deleted_indices = 0; u32 adds = 0, deletes = 0; f64 before, after; clib_time_init (&tm->clib_time); tw_timer_wheel_init_1t_3w_1024sl_ov (&tm->triple_ov_wheel, expired_timer_triple_ov_callback, 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 75700; run_triple_ov_wheel (&tm->triple_ov_wheel, initial_wheel_offset); fformat (stdout, "initial wheel time %d, fi %d si %d gi %d\n", tm->triple_ov_wheel.current_tick, tm->triple_ov_wheel.current_index[TW_TIMER_RING_FAST], tm->triple_ov_wheel.current_index[TW_TIMER_RING_SLOW], tm->triple_ov_wheel.current_index[TW_TIMER_RING_GLACIER]); initial_wheel_offset = tm->triple_ov_wheel.current_tick; fformat (stdout, "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n", tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed); before = clib_time_now (&tm->clib_time); /* Prime the pump */ for (i = 0; i < tm->ntimers; i++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + initial_wheel_offset; e->stop_timer_handle = tw_timer_start_1t_3w_1024sl_ov (&tm->triple_ov_wheel, e - tm->test_elts, 0 /* timer id */ , expiration_time); } adds += i; for (i = 0; i < tm->niter; i++) { run_triple_ov_wheel (&tm->triple_ov_wheel, tm->ticks_per_iter); j = 0; vec_reset_length (deleted_indices); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { tw_timer_stop_1t_3w_1024sl_ov (&tm->triple_ov_wheel, e->stop_timer_handle); vec_add1 (deleted_indices, e - tm->test_elts); if (++j >= tm->ntimers / 4) goto del_and_re_add; } /* *INDENT-ON* */ del_and_re_add: for (j = 0; j < vec_len (deleted_indices); j++) pool_put_index (tm->test_elts, deleted_indices[j]); deletes += j; for (j = 0; j < tm->ntimers / 4; j++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); do { expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1); } while (expiration_time == 0); if (expiration_time > max_expiration_time) max_expiration_time = expiration_time; e->expected_to_expire = expiration_time + tm->triple_ov_wheel.current_tick; e->stop_timer_handle = tw_timer_start_1t_3w_1024sl_ov (&tm->triple_ov_wheel, e - tm->test_elts, 0 /* timer id */ , expiration_time); } adds += j; } vec_free (deleted_indices); run_triple_ov_wheel (&tm->triple_ov_wheel, max_expiration_time + 1); after = clib_time_now (&tm->clib_time); fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes, tm->triple_ov_wheel.current_tick); fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n", (after - before), ((f64) adds + (f64) deletes + (f64) tm->triple_ov_wheel.current_tick) / (after - before)); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { TWT (tw_timer) * t; fformat (stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); t = pool_elt_at_index (tm->triple_ov_wheel.timers, e->stop_timer_handle); fformat (stdout, " expiration_time %lld\n", t->expiration_time); } /* *INDENT-ON* */ pool_free (tm->test_elts); tw_timer_wheel_free_1t_3w_1024sl_ov (&tm->triple_ov_wheel); return 0; } static clib_error_t * test1_single (tw_timer_test_main_t * tm) { u32 i; tw_timer_test_elt_t *e; u32 offset; tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel, expired_timer_single_callback, 1.0 /* timer interval */ , ~0); /* * Prime offset, to make sure that the wheel starts in a * non-trivial position */ offset = 123; run_single_wheel (&tm->single_wheel, offset); fformat (stdout, "initial wheel time %d, fast index %d\n", tm->single_wheel.current_tick, tm->single_wheel.current_index[TW_TIMER_RING_FAST]); offset = tm->single_wheel.current_tick; for (i = 0; i < tm->ntimers; i++) { u32 expected_to_expire; u32 timer_arg; timer_arg = 1 + i; timer_arg &= 2047; if (timer_arg == 0) timer_arg = 1; expected_to_expire = timer_arg + tm->single_wheel.current_tick; pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); e->expected_to_expire = expected_to_expire; e->stop_timer_handle = tw_timer_start_2t_1w_2048sl (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ , timer_arg); } run_single_wheel (&tm->single_wheel, tm->ntimers + 3); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { fformat(stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); } /* *INDENT-ON* */ fformat (stdout, "final wheel time %d, fast index %d\n", tm->single_wheel.current_tick, tm->single_wheel.current_index[TW_TIMER_RING_FAST]); pool_free (tm->test_elts); tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel); return 0; } static clib_error_t * test1_double (tw_timer_test_main_t * tm) { u32 i; tw_timer_test_elt_t *e; u32 offset; tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel, expired_timer_double_callback, 1.0 /* timer interval */ , ~0); /* * Prime offset, to make sure that the wheel starts in a * non-trivial position */ offset = 227989; run_double_wheel (&tm->double_wheel, offset); fformat (stdout, "initial wheel time %d, fast index %d\n", tm->double_wheel.current_tick, tm->double_wheel.current_index[TW_TIMER_RING_FAST]); for (i = 0; i < tm->ntimers; i++) { pool_get (tm->test_elts, e); clib_memset (e, 0, sizeof (*e)); e->expected_to_expire = i + tm->double_wheel.current_tick + 1; e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ , i + 1); } run_double_wheel (&tm->double_wheel, tm->ntimers + 3); if (pool_elts (tm->test_elts)) fformat (stdout, "Note: %d elements remain in pool\n", pool_elts (tm->test_elts)); /* *INDENT-OFF* */ pool_foreach (e, tm->test_elts) { fformat(stdout, "[%d] expected to expire %d\n", e - tm->test_elts, e->expected_to_expire); } /* *INDENT-ON* */ fformat (stdout, "final wheel time %d, fast index %d\n", tm->double_wheel.current_tick, tm->double_wheel.current_index[TW_TIMER_RING_FAST]); pool_free (tm->test_elts); tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel); return 0; } static clib_error_t * test1_two_timer_double (tw_timer_test_main_t * tm)
# Copyright (c) 2022 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Constants used in CSIT.

"Constant" means a value that keeps its value since initialization. The value
does not need to be hard coded here, but can be read from environment variables.
"""


import os


def get_str_from_env(env_var_names, default_value):
    """Attempt to read string from environment variable, return that or default.

    If environment variable exists, but is empty (and default is not),
    empty string is returned.

    Several environment variable names are examined, as CSIT currently supports
    a mix of naming conventions.
    Here "several" means there are hard coded prefixes to try,
    and env_var_names itself can be single name, or a list or a tuple of names.

    :param env_var_names: Base names of environment variable to attempt to read.
    :param default_value: Value to return if the env var does not exist.
    :type env_var_names: str, or list of str, or tuple of str
    :type default_value: str