blob: bde958f3ca2507c3833cfd982c9e4ab4af55ce1a [file] [log] [blame]
Dave Barach8e8f98c2017-02-03 11:58:53 -05001#include <vppinfra/time.h>
2#include <vppinfra/cache.h>
3#include <vppinfra/error.h>
4#include <vppinfra/tw_timer_2t_1w_2048sl.h>
5#include <vppinfra/tw_timer_16t_2w_512sl.h>
Dave Barach4af9ba12017-06-07 15:18:23 -04006#include <vppinfra/tw_timer_4t_3w_256sl.h>
7#include <vppinfra/tw_timer_1t_3w_1024sl_ov.h>
Dave Barach8e8f98c2017-02-03 11:58:53 -05008
9typedef struct
10{
11 /** Handle returned from tw_start_timer */
12 u32 stop_timer_handle;
13
14 /** Test item should expire at this clock tick */
Dave Barach4af9ba12017-06-07 15:18:23 -040015 u64 expected_to_expire;
Dave Barach8e8f98c2017-02-03 11:58:53 -050016} tw_timer_test_elt_t;
17
18typedef struct
19{
20 /** Pool of test objects */
21 tw_timer_test_elt_t *test_elts;
22
23 /** The single-wheel */
24 tw_timer_wheel_2t_1w_2048sl_t single_wheel;
25
26 /** The double-wheel */
27 tw_timer_wheel_16t_2w_512sl_t double_wheel;
28
Dave Barach4af9ba12017-06-07 15:18:23 -040029 /* The triple wheel */
30 tw_timer_wheel_4t_3w_256sl_t triple_wheel;
31
32 /* The triple wheel with overflow vector */
33 tw_timer_wheel_1t_3w_1024sl_ov_t triple_ov_wheel;
34
Dave Barach8e8f98c2017-02-03 11:58:53 -050035 /** random number seed */
Dave Barach4af9ba12017-06-07 15:18:23 -040036 u64 seed;
Dave Barach8e8f98c2017-02-03 11:58:53 -050037
38 /** number of timers */
39 u32 ntimers;
40
41 /** number of "churn" iterations */
42 u32 niter;
43
44 /** number of clock ticks per churn iteration */
45 u32 ticks_per_iter;
46
47 /** cpu timer */
48 clib_time_t clib_time;
49} tw_timer_test_main_t;
50
51tw_timer_test_main_t tw_timer_test_main;
52
53static void
54run_single_wheel (tw_timer_wheel_2t_1w_2048sl_t * tw, u32 n_ticks)
55{
56 u32 i;
57 f64 now = tw->last_run_time + 1.01;
58
59 for (i = 0; i < n_ticks; i++)
60 {
61 tw_timer_expire_timers_2t_1w_2048sl (tw, now);
62 now += 1.01;
63 }
64}
65
66static void
67run_double_wheel (tw_timer_wheel_16t_2w_512sl_t * tw, u32 n_ticks)
68{
69 u32 i;
70 f64 now = tw->last_run_time + 1.01;
71
72 for (i = 0; i < n_ticks; i++)
73 {
74 tw_timer_expire_timers_16t_2w_512sl (tw, now);
75 now += 1.01;
76 }
77}
78
79static void
Dave Barach4af9ba12017-06-07 15:18:23 -040080run_triple_wheel (tw_timer_wheel_4t_3w_256sl_t * tw, u32 n_ticks)
81{
82 u32 i;
83 f64 now = tw->last_run_time + 1.01;
84
85 for (i = 0; i < n_ticks; i++)
86 {
87 tw_timer_expire_timers_4t_3w_256sl (tw, now);
88 now += 1.01;
89 }
90}
91
92static void
93run_triple_ov_wheel (tw_timer_wheel_1t_3w_1024sl_ov_t * tw, u32 n_ticks)
94{
95 u32 i;
96 f64 now = tw->last_run_time + 1.01;
97
98 for (i = 0; i < n_ticks; i++)
99 {
100 tw_timer_expire_timers_1t_3w_1024sl_ov (tw, now);
101 now += 1.01;
102 }
103}
104
105static void
Dave Barach8e8f98c2017-02-03 11:58:53 -0500106expired_timer_single_callback (u32 * expired_timers)
107{
108 int i;
109 u32 pool_index, timer_id;
110 tw_timer_test_elt_t *e;
111 tw_timer_test_main_t *tm = &tw_timer_test_main;
112
113 for (i = 0; i < vec_len (expired_timers); i++)
114 {
115 pool_index = expired_timers[i] & 0x7FFFFFFF;
116 timer_id = expired_timers[i] >> 31;
117
118 ASSERT (timer_id == 1);
119
120 e = pool_elt_at_index (tm->test_elts, pool_index);
121
122 if (e->expected_to_expire != tm->single_wheel.current_tick)
123 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400124 fformat (stdout, "[%d] expired at %lld not %lld\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500125 e - tm->test_elts, tm->single_wheel.current_tick,
126 e->expected_to_expire);
127 }
128 pool_put (tm->test_elts, e);
129 }
130}
131
132static void
133expired_timer_double_callback (u32 * expired_timers)
134{
135 int i;
136 u32 pool_index, timer_id;
137 tw_timer_test_elt_t *e;
138 tw_timer_test_main_t *tm = &tw_timer_test_main;
139
140 for (i = 0; i < vec_len (expired_timers); i++)
141 {
142 pool_index = expired_timers[i] & 0x0FFFFFFF;
143 timer_id = expired_timers[i] >> 28;
144
145 ASSERT (timer_id == 14);
146
147 e = pool_elt_at_index (tm->test_elts, pool_index);
148
149 if (e->expected_to_expire != tm->double_wheel.current_tick)
150 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400151 fformat (stdout, "[%d] expired at %lld not %lld\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500152 e - tm->test_elts, tm->double_wheel.current_tick,
153 e->expected_to_expire);
154 }
155 pool_put (tm->test_elts, e);
156 }
157}
158
Dave Barach4af9ba12017-06-07 15:18:23 -0400159static void
160expired_timer_triple_callback (u32 * expired_timers)
161{
162 int i;
163 u32 pool_index, timer_id;
164 tw_timer_test_elt_t *e;
165 tw_timer_test_main_t *tm = &tw_timer_test_main;
166
167 for (i = 0; i < vec_len (expired_timers); i++)
168 {
169 pool_index = expired_timers[i] & 0x3FFFFFFF;
170 timer_id = expired_timers[i] >> 30;
171
172 ASSERT (timer_id == 3);
173
174 e = pool_elt_at_index (tm->test_elts, pool_index);
175
176 if (e->expected_to_expire != tm->triple_wheel.current_tick)
177 {
178 fformat (stdout, "[%d] expired at %lld not %lld\n",
179 e - tm->test_elts, tm->triple_wheel.current_tick,
180 e->expected_to_expire);
181 }
182 pool_put (tm->test_elts, e);
183 }
184}
185
186static void
187expired_timer_triple_ov_callback (u32 * expired_timers)
188{
189 int i;
190 u32 pool_index;
191 tw_timer_test_elt_t *e;
192 tw_timer_test_main_t *tm = &tw_timer_test_main;
193
194 for (i = 0; i < vec_len (expired_timers); i++)
195 {
196 pool_index = expired_timers[i];
197
198 e = pool_elt_at_index (tm->test_elts, pool_index);
199
200 if (e->expected_to_expire != tm->triple_ov_wheel.current_tick)
201 {
202 fformat (stdout, "[%d] expired at %lld not %lld\n",
203 e - tm->test_elts, tm->triple_ov_wheel.current_tick,
204 e->expected_to_expire);
205 }
206 pool_put (tm->test_elts, e);
207 }
208}
209
Dave Barach8e8f98c2017-02-03 11:58:53 -0500210static clib_error_t *
211test2_single (tw_timer_test_main_t * tm)
212{
213 u32 i, j;
214 tw_timer_test_elt_t *e;
215 u32 initial_wheel_offset;
Dave Barach4af9ba12017-06-07 15:18:23 -0400216 u64 expiration_time;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500217 u32 max_expiration_time = 0;
218 u32 *deleted_indices = 0;
219 u32 adds = 0, deletes = 0;
220 f64 before, after;
221
222 clib_time_init (&tm->clib_time);
223
224 tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel,
225 expired_timer_single_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200226 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500227
228 /* Prime offset */
229 initial_wheel_offset = 757;
230
231 run_single_wheel (&tm->single_wheel, initial_wheel_offset);
232
Dave Barach4af9ba12017-06-07 15:18:23 -0400233 fformat (stdout, "initial wheel time %d, fast index %d\n",
234 tm->single_wheel.current_tick,
235 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
236
237 initial_wheel_offset = tm->single_wheel.current_tick;
238
239 fformat (stdout,
240 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500241 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
242
243 before = clib_time_now (&tm->clib_time);
244
245 /* Prime the pump */
246 for (i = 0; i < tm->ntimers; i++)
247 {
248 pool_get (tm->test_elts, e);
249 memset (e, 0, sizeof (*e));
250
251 do
252 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400253 expiration_time = random_u64 (&tm->seed) & (2047);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500254 }
255 while (expiration_time == 0);
256
257 if (expiration_time > max_expiration_time)
258 max_expiration_time = expiration_time;
259
260 e->expected_to_expire = expiration_time + initial_wheel_offset;
261 e->stop_timer_handle =
262 tw_timer_start_2t_1w_2048sl (&tm->single_wheel, e - tm->test_elts,
263 1 /* timer id */ ,
264 expiration_time);
265 }
266
267 adds += i;
268
269 for (i = 0; i < tm->niter; i++)
270 {
271 run_single_wheel (&tm->single_wheel, tm->ticks_per_iter);
272
273 j = 0;
274 vec_reset_length (deleted_indices);
275 /* *INDENT-OFF* */
276 pool_foreach (e, tm->test_elts,
277 ({
278 tw_timer_stop_2t_1w_2048sl (&tm->single_wheel, e->stop_timer_handle);
279 vec_add1 (deleted_indices, e - tm->test_elts);
280 if (++j >= tm->ntimers / 4)
281 goto del_and_re_add;
282 }));
283 /* *INDENT-ON* */
284
285 del_and_re_add:
286 for (j = 0; j < vec_len (deleted_indices); j++)
Dave Barach4af9ba12017-06-07 15:18:23 -0400287 {
288 pool_put_index (tm->test_elts, deleted_indices[j]);
289 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500290
291 deletes += j;
292
293 for (j = 0; j < tm->ntimers / 4; j++)
294 {
295 pool_get (tm->test_elts, e);
296 memset (e, 0, sizeof (*e));
297
298 do
299 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400300 expiration_time = random_u64 (&tm->seed) & (2047);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500301 }
302 while (expiration_time == 0);
303
304 if (expiration_time > max_expiration_time)
305 max_expiration_time = expiration_time;
306
307 e->expected_to_expire =
308 expiration_time + tm->single_wheel.current_tick;
309 e->stop_timer_handle = tw_timer_start_2t_1w_2048sl
310 (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ ,
311 expiration_time);
312 }
313 adds += j;
314 }
315
316 vec_free (deleted_indices);
317
318 run_single_wheel (&tm->single_wheel, max_expiration_time + 1);
319
320 after = clib_time_now (&tm->clib_time);
321
322 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
323 tm->single_wheel.current_tick);
324 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
325 (after - before),
326 ((f64) adds + (f64) deletes +
327 (f64) tm->single_wheel.current_tick) / (after - before));
328
329 if (pool_elts (tm->test_elts))
330 fformat (stdout, "Note: %d elements remain in pool\n",
331 pool_elts (tm->test_elts));
332
333 /* *INDENT-OFF* */
334 pool_foreach (e, tm->test_elts,
335 ({
336 fformat (stdout, "[%d] expected to expire %d\n",
337 e - tm->test_elts,
338 e->expected_to_expire);
339 }));
340 /* *INDENT-ON* */
341
342 pool_free (tm->test_elts);
343 tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel);
344 return 0;
345}
346
347static clib_error_t *
348test2_double (tw_timer_test_main_t * tm)
349{
350 u32 i, j;
351 tw_timer_test_elt_t *e;
352 u32 initial_wheel_offset;
353 u32 expiration_time;
354 u32 max_expiration_time = 0;
355 u32 *deleted_indices = 0;
356 u32 adds = 0, deletes = 0;
357 f64 before, after;
358
359 clib_time_init (&tm->clib_time);
360
361 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
362 expired_timer_double_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200363 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500364
365 /* Prime offset */
Dave Barach4af9ba12017-06-07 15:18:23 -0400366 initial_wheel_offset = 7577;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500367
368 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
369
Dave Barach4af9ba12017-06-07 15:18:23 -0400370 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
371 tm->double_wheel.current_tick,
372 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
373 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
374
375 initial_wheel_offset = tm->double_wheel.current_tick;
376
377 fformat (stdout,
378 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500379 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
380
381 before = clib_time_now (&tm->clib_time);
382
383 /* Prime the pump */
384 for (i = 0; i < tm->ntimers; i++)
385 {
386 pool_get (tm->test_elts, e);
387 memset (e, 0, sizeof (*e));
388
389 do
390 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400391 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500392 }
393 while (expiration_time == 0);
394
395 if (expiration_time > max_expiration_time)
396 max_expiration_time = expiration_time;
397
398 e->expected_to_expire = expiration_time + initial_wheel_offset;
Dave Barach4af9ba12017-06-07 15:18:23 -0400399
Dave Barach8e8f98c2017-02-03 11:58:53 -0500400 e->stop_timer_handle =
401 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
402 14 /* timer id */ ,
403 expiration_time);
404 }
405
406 adds += i;
407
408 for (i = 0; i < tm->niter; i++)
409 {
410 run_double_wheel (&tm->double_wheel, tm->ticks_per_iter);
411
412 j = 0;
413 vec_reset_length (deleted_indices);
414 /* *INDENT-OFF* */
415 pool_foreach (e, tm->test_elts,
416 ({
417 tw_timer_stop_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle);
418 vec_add1 (deleted_indices, e - tm->test_elts);
419 if (++j >= tm->ntimers / 4)
420 goto del_and_re_add;
421 }));
422 /* *INDENT-ON* */
423
424 del_and_re_add:
425 for (j = 0; j < vec_len (deleted_indices); j++)
426 pool_put_index (tm->test_elts, deleted_indices[j]);
427
428 deletes += j;
429
430 for (j = 0; j < tm->ntimers / 4; j++)
431 {
432 pool_get (tm->test_elts, e);
433 memset (e, 0, sizeof (*e));
434
435 do
436 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400437 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500438 }
439 while (expiration_time == 0);
440
441 if (expiration_time > max_expiration_time)
442 max_expiration_time = expiration_time;
443
444 e->expected_to_expire = expiration_time +
445 tm->double_wheel.current_tick;
Dave Barach4af9ba12017-06-07 15:18:23 -0400446
Dave Barach8e8f98c2017-02-03 11:58:53 -0500447 e->stop_timer_handle = tw_timer_start_16t_2w_512sl
448 (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ ,
449 expiration_time);
450 }
451 adds += j;
452 }
453
454 vec_free (deleted_indices);
455
456 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
457
458 after = clib_time_now (&tm->clib_time);
459
460 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
461 tm->double_wheel.current_tick);
462 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
463 (after - before),
464 ((f64) adds + (f64) deletes +
465 (f64) tm->double_wheel.current_tick) / (after - before));
466
467 if (pool_elts (tm->test_elts))
468 fformat (stdout, "Note: %d elements remain in pool\n",
469 pool_elts (tm->test_elts));
470
471 /* *INDENT-OFF* */
472 pool_foreach (e, tm->test_elts,
473 ({
474 fformat (stdout, "[%d] expected to expire %d\n",
475 e - tm->test_elts,
476 e->expected_to_expire);
477 }));
478 /* *INDENT-ON* */
479
480 pool_free (tm->test_elts);
481 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
482 return 0;
483}
484
Florin Corasadb5bd52018-06-22 15:29:38 -0700485static u32
486get_expiration_time (tw_timer_test_main_t * tm)
487{
488 u32 expiration_time;
489 do
490 {
491 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
492 }
493 while (expiration_time == 0);
494 return expiration_time;
495}
496
497static clib_error_t *
498test2_double_updates (tw_timer_test_main_t * tm)
499{
500 u32 i, j;
501 tw_timer_test_elt_t *e;
502 u32 initial_wheel_offset;
503 u32 expiration_time;
504 u32 max_expiration_time = 0, updates = 0;
505 f64 before, after;
506
507 clib_time_init (&tm->clib_time);
508 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
509 expired_timer_double_callback,
510 1.0 /* timer interval */ , ~0);
511
512 /* Prime offset */
513 initial_wheel_offset = 7577;
514 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
515 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
516 tm->double_wheel.current_tick,
517 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
518 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
519
520 initial_wheel_offset = tm->double_wheel.current_tick;
521 fformat (stdout,
522 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
523 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
524
525 before = clib_time_now (&tm->clib_time);
526
527 /* Prime the pump */
528 for (i = 0; i < tm->ntimers; i++)
529 {
530 pool_get (tm->test_elts, e);
531 memset (e, 0, sizeof (*e));
532
533 expiration_time = get_expiration_time (tm);
534 max_expiration_time = clib_max (expiration_time, max_expiration_time);
535
536 e->expected_to_expire = expiration_time + initial_wheel_offset;
537 e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel,
538 e - tm->test_elts,
539 14 /* timer id */ ,
540 expiration_time);
541 }
542
543 for (i = 0; i < tm->niter; i++)
544 {
545 run_double_wheel (&tm->double_wheel, tm->ticks_per_iter);
546
547 j = 0;
548
549 /* *INDENT-OFF* */
550 pool_foreach (e, tm->test_elts,
551 ({
552 expiration_time = get_expiration_time (tm);
553 max_expiration_time = clib_max (expiration_time, max_expiration_time);
554 e->expected_to_expire = expiration_time
555 + tm->double_wheel.current_tick;
556 tw_timer_update_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle,
557 expiration_time);
558 if (++j >= tm->ntimers / 4)
559 goto done;
560 }));
561 /* *INDENT-ON* */
562
563 done:
564 updates += j;
565 }
566
567 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
568
569 after = clib_time_now (&tm->clib_time);
570
571 fformat (stdout, "%d updates, %d ticks\n", updates,
572 tm->double_wheel.current_tick);
573 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
574 (after - before),
575 ((f64) updates + (f64) tm->double_wheel.current_tick) / (after -
576 before));
577
578 if (pool_elts (tm->test_elts))
579 fformat (stdout, "Note: %d elements remain in pool\n",
580 pool_elts (tm->test_elts));
581
582 /* *INDENT-OFF* */
583 pool_foreach (e, tm->test_elts,
584 ({
585 fformat (stdout, "[%d] expected to expire %d\n",
586 e - tm->test_elts,
587 e->expected_to_expire);
588 }));
589 /* *INDENT-ON* */
590
591 pool_free (tm->test_elts);
592 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
593 return 0;
594}
595
Dave Barach8e8f98c2017-02-03 11:58:53 -0500596static clib_error_t *
Dave Barach4af9ba12017-06-07 15:18:23 -0400597test2_triple (tw_timer_test_main_t * tm)
598{
599 u32 i, j;
600 tw_timer_test_elt_t *e;
601 u32 initial_wheel_offset = 0;
602 u32 expiration_time;
603 u32 max_expiration_time = 0;
604 u32 *deleted_indices = 0;
605 u32 adds = 0, deletes = 0;
606 f64 before, after;
607
608 clib_time_init (&tm->clib_time);
609
610 tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel,
611 expired_timer_triple_callback,
612 1.0 /* timer interval */ , ~0);
613
614
615 /* Prime offset */
616 initial_wheel_offset = 75700;
617 run_triple_wheel (&tm->triple_wheel, initial_wheel_offset);
618
619 fformat (stdout,
620 "initial wheel time %d, fi %d si %d gi %d\n",
621 tm->triple_wheel.current_tick,
622 tm->triple_wheel.current_index[TW_TIMER_RING_FAST],
623 tm->triple_wheel.current_index[TW_TIMER_RING_SLOW],
624 tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]);
625
626 initial_wheel_offset = tm->triple_wheel.current_tick;
627
628 fformat (stdout,
629 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
630 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
631
632 before = clib_time_now (&tm->clib_time);
633
634 /* Prime the pump */
635 for (i = 0; i < tm->ntimers; i++)
636 {
637 pool_get (tm->test_elts, e);
638 memset (e, 0, sizeof (*e));
639
640 do
641 {
642 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
643 }
644 while (expiration_time == 0);
645
646 if (expiration_time > max_expiration_time)
647 max_expiration_time = expiration_time;
648
649 e->expected_to_expire = expiration_time + initial_wheel_offset;
650
651 e->stop_timer_handle =
652 tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts,
653 3 /* timer id */ ,
654 expiration_time);
655 }
656
657 adds += i;
658
659 for (i = 0; i < tm->niter; i++)
660 {
661 run_triple_wheel (&tm->triple_wheel, tm->ticks_per_iter);
662
663 j = 0;
664 vec_reset_length (deleted_indices);
665 /* *INDENT-OFF* */
666 pool_foreach (e, tm->test_elts,
667 ({
668 tw_timer_stop_4t_3w_256sl (&tm->triple_wheel, e->stop_timer_handle);
669 vec_add1 (deleted_indices, e - tm->test_elts);
670 if (++j >= tm->ntimers / 4)
671 goto del_and_re_add;
672 }));
673 /* *INDENT-ON* */
674
675 del_and_re_add:
676 for (j = 0; j < vec_len (deleted_indices); j++)
677 pool_put_index (tm->test_elts, deleted_indices[j]);
678
679 deletes += j;
680
681 for (j = 0; j < tm->ntimers / 4; j++)
682 {
683 pool_get (tm->test_elts, e);
684 memset (e, 0, sizeof (*e));
685
686 do
687 {
688 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
689 }
690 while (expiration_time == 0);
691
692 if (expiration_time > max_expiration_time)
693 max_expiration_time = expiration_time;
694
695 e->expected_to_expire = expiration_time +
696 tm->triple_wheel.current_tick;
697
698 e->stop_timer_handle = tw_timer_start_4t_3w_256sl
699 (&tm->triple_wheel, e - tm->test_elts, 3 /* timer id */ ,
700 expiration_time);
701 }
702 adds += j;
703 }
704
705 vec_free (deleted_indices);
706
707 run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1);
708
709 after = clib_time_now (&tm->clib_time);
710
711 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
712 tm->triple_wheel.current_tick);
713 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
714 (after - before),
715 ((f64) adds + (f64) deletes +
716 (f64) tm->triple_wheel.current_tick) / (after - before));
717
718 if (pool_elts (tm->test_elts))
719 fformat (stdout, "Note: %d elements remain in pool\n",
720 pool_elts (tm->test_elts));
721
722 /* *INDENT-OFF* */
723 pool_foreach (e, tm->test_elts,
724 ({
725 fformat (stdout, "[%d] expected to expire %d\n",
726 e - tm->test_elts,
727 e->expected_to_expire);
728 }));
729 /* *INDENT-ON* */
730
731 pool_free (tm->test_elts);
732 tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel);
733 return 0;
734}
735
736static clib_error_t *
737test2_triple_ov (tw_timer_test_main_t * tm)
738{
739 u32 i, j;
740 tw_timer_test_elt_t *e;
741 u32 initial_wheel_offset = 0;
742 u32 expiration_time;
743 u32 max_expiration_time = 0;
744 u32 *deleted_indices = 0;
745 u32 adds = 0, deletes = 0;
746 f64 before, after;
747
748 clib_time_init (&tm->clib_time);
749
750 tw_timer_wheel_init_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
751 expired_timer_triple_ov_callback,
752 1.0 /* timer interval */ , ~0);
753
754
755 /* Prime offset */
756 initial_wheel_offset = 75700;
757 run_triple_ov_wheel (&tm->triple_ov_wheel, initial_wheel_offset);
758
759 fformat (stdout,
760 "initial wheel time %d, fi %d si %d gi %d\n",
761 tm->triple_ov_wheel.current_tick,
762 tm->triple_ov_wheel.current_index[TW_TIMER_RING_FAST],
763 tm->triple_ov_wheel.current_index[TW_TIMER_RING_SLOW],
764 tm->triple_ov_wheel.current_index[TW_TIMER_RING_GLACIER]);
765
766 initial_wheel_offset = tm->triple_ov_wheel.current_tick;
767
768 fformat (stdout,
769 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
770 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
771
772 before = clib_time_now (&tm->clib_time);
773
774 /* Prime the pump */
775 for (i = 0; i < tm->ntimers; i++)
776 {
777 pool_get (tm->test_elts, e);
778 memset (e, 0, sizeof (*e));
779
780 do
781 {
782 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
783 }
784 while (expiration_time == 0);
785
786 if (expiration_time > max_expiration_time)
787 max_expiration_time = expiration_time;
788
789 e->expected_to_expire = expiration_time + initial_wheel_offset;
790
791 e->stop_timer_handle =
792 tw_timer_start_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
793 e - tm->test_elts, 0 /* timer id */ ,
794 expiration_time);
795 }
796
797 adds += i;
798
799 for (i = 0; i < tm->niter; i++)
800 {
801 run_triple_ov_wheel (&tm->triple_ov_wheel, tm->ticks_per_iter);
802
803 j = 0;
804 vec_reset_length (deleted_indices);
805 /* *INDENT-OFF* */
806 pool_foreach (e, tm->test_elts,
807 ({
808 tw_timer_stop_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
809 e->stop_timer_handle);
810 vec_add1 (deleted_indices, e - tm->test_elts);
811 if (++j >= tm->ntimers / 4)
812 goto del_and_re_add;
813 }));
814 /* *INDENT-ON* */
815
816 del_and_re_add:
817 for (j = 0; j < vec_len (deleted_indices); j++)
818 pool_put_index (tm->test_elts, deleted_indices[j]);
819
820 deletes += j;
821
822 for (j = 0; j < tm->ntimers / 4; j++)
823 {
824 pool_get (tm->test_elts, e);
825 memset (e, 0, sizeof (*e));
826
827 do
828 {
829 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
830 }
831 while (expiration_time == 0);
832
833 if (expiration_time > max_expiration_time)
834 max_expiration_time = expiration_time;
835
836 e->expected_to_expire = expiration_time +
837 tm->triple_ov_wheel.current_tick;
838
839 e->stop_timer_handle = tw_timer_start_1t_3w_1024sl_ov
840 (&tm->triple_ov_wheel, e - tm->test_elts, 0 /* timer id */ ,
841 expiration_time);
842 }
843 adds += j;
844 }
845
846 vec_free (deleted_indices);
847
848 run_triple_ov_wheel (&tm->triple_ov_wheel, max_expiration_time + 1);
849
850 after = clib_time_now (&tm->clib_time);
851
852 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
853 tm->triple_ov_wheel.current_tick);
854 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
855 (after - before),
856 ((f64) adds + (f64) deletes +
857 (f64) tm->triple_ov_wheel.current_tick) / (after - before));
858
859 if (pool_elts (tm->test_elts))
860 fformat (stdout, "Note: %d elements remain in pool\n",
861 pool_elts (tm->test_elts));
862
863 /* *INDENT-OFF* */
864 pool_foreach (e, tm->test_elts,
865 ({
866 TWT (tw_timer) * t;
867
868 fformat (stdout, "[%d] expected to expire %d\n",
869 e - tm->test_elts,
870 e->expected_to_expire);
871 t = pool_elt_at_index (tm->triple_ov_wheel.timers, e->stop_timer_handle);
872 fformat (stdout, " expiration_time %lld\n", t->expiration_time);
873 }));
874 /* *INDENT-ON* */
875
876 pool_free (tm->test_elts);
877 tw_timer_wheel_free_1t_3w_1024sl_ov (&tm->triple_ov_wheel);
878 return 0;
879}
880
881static clib_error_t *
Dave Barach8e8f98c2017-02-03 11:58:53 -0500882test1_single (tw_timer_test_main_t * tm)
883{
884 u32 i;
885 tw_timer_test_elt_t *e;
886 u32 offset;
887
888 tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel,
889 expired_timer_single_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200890 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500891
892 /*
893 * Prime offset, to make sure that the wheel starts in a
894 * non-trivial position
895 */
896 offset = 123;
897
898 run_single_wheel (&tm->single_wheel, offset);
899
900 fformat (stdout, "initial wheel time %d, fast index %d\n",
901 tm->single_wheel.current_tick,
902 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
903
Dave Barach4af9ba12017-06-07 15:18:23 -0400904 offset = tm->single_wheel.current_tick;
905
Dave Barach8e8f98c2017-02-03 11:58:53 -0500906 for (i = 0; i < tm->ntimers; i++)
907 {
908 u32 expected_to_expire;
909 u32 timer_arg;
910
911 timer_arg = 1 + i;
912 timer_arg &= 2047;
913 if (timer_arg == 0)
914 timer_arg = 1;
915
916 expected_to_expire = timer_arg + offset;
917
918 pool_get (tm->test_elts, e);
919 memset (e, 0, sizeof (*e));
920 e->expected_to_expire = expected_to_expire;
921 e->stop_timer_handle = tw_timer_start_2t_1w_2048sl
922 (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ ,
923 timer_arg);
924 }
925 run_single_wheel (&tm->single_wheel, tm->ntimers + 3);
926
927 if (pool_elts (tm->test_elts))
928 fformat (stdout, "Note: %d elements remain in pool\n",
929 pool_elts (tm->test_elts));
930
931 /* *INDENT-OFF* */
932 pool_foreach (e, tm->test_elts,
933 ({
934 fformat(stdout, "[%d] expected to expire %d\n",
935 e - tm->test_elts,
936 e->expected_to_expire);
937 }));
938 /* *INDENT-ON* */
939
940 fformat (stdout,
941 "final wheel time %d, fast index %d\n",
942 tm->single_wheel.current_tick,
943 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
944
945 pool_free (tm->test_elts);
946 tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel);
947 return 0;
948}
949
950static clib_error_t *
951test1_double (tw_timer_test_main_t * tm)
952{
953 u32 i;
954 tw_timer_test_elt_t *e;
955 u32 offset;
956
957 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
958 expired_timer_double_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200959 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500960
961 /*
962 * Prime offset, to make sure that the wheel starts in a
963 * non-trivial position
964 */
965 offset = 227989;
966
967 run_double_wheel (&tm->double_wheel, offset);
968
969 fformat (stdout, "initial wheel time %d, fast index %d\n",
970 tm->double_wheel.current_tick,
971 tm->double_wheel.current_index[TW_TIMER_RING_FAST]);
972
973 for (i = 0; i < tm->ntimers; i++)
974 {
975 pool_get (tm->test_elts, e);
976 memset (e, 0, sizeof (*e));
977
978 e->expected_to_expire = i + offset + 1;
979 e->stop_timer_handle = tw_timer_start_16t_2w_512sl
980 (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ ,
981 i + 1);
982 }
983 run_double_wheel (&tm->double_wheel, tm->ntimers + 3);
984
985 if (pool_elts (tm->test_elts))
986 fformat (stdout, "Note: %d elements remain in pool\n",
987 pool_elts (tm->test_elts));
988
989 /* *INDENT-OFF* */
990 pool_foreach (e, tm->test_elts,
991 ({
992 fformat(stdout, "[%d] expected to expire %d\n",
993 e - tm->test_elts,
994 e->expected_to_expire);
995 }));
996 /* *INDENT-ON* */
997
998 fformat (stdout,
999 "final wheel time %d, fast index %d\n",
1000 tm->double_wheel.current_tick,
1001 tm->double_wheel.current_index[TW_TIMER_RING_FAST]);
1002
1003 pool_free (tm->test_elts);
1004 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1005 return 0;
1006}
1007
1008static clib_error_t *
Dave Barach4af9ba12017-06-07 15:18:23 -04001009test3_triple_double (tw_timer_test_main_t * tm)
1010{
1011 tw_timer_test_elt_t *e;
1012 u32 initial_wheel_offset = 0;
1013 u32 expiration_time;
1014 u32 max_expiration_time = 0;
1015 u32 adds = 0, deletes = 0;
1016 f64 before, after;
1017
1018 clib_time_init (&tm->clib_time);
1019
1020 tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel,
1021 expired_timer_triple_callback,
1022 1.0 /* timer interval */ , ~0);
1023
1024 initial_wheel_offset = 0;
1025 run_triple_wheel (&tm->triple_wheel, initial_wheel_offset);
1026
1027 fformat (stdout,
1028 "initial wheel time %d, fi %d si %d gi %d\n",
1029 tm->triple_wheel.current_tick,
1030 tm->triple_wheel.current_index[TW_TIMER_RING_FAST],
1031 tm->triple_wheel.current_index[TW_TIMER_RING_SLOW],
1032 tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]);
1033
1034 initial_wheel_offset = tm->triple_wheel.current_tick;
1035
1036 fformat (stdout, "Create a timer which expires at wheel-time (1, 0, 0)\n");
1037
1038 before = clib_time_now (&tm->clib_time);
1039
1040 /* Prime the pump */
1041 pool_get (tm->test_elts, e);
1042 memset (e, 0, sizeof (*e));
1043
1044 /* 1 glacier ring tick from now */
1045 expiration_time = TW_SLOTS_PER_RING * TW_SLOTS_PER_RING;
1046 e->expected_to_expire = expiration_time + initial_wheel_offset;
1047 max_expiration_time = expiration_time;
1048
1049 e->stop_timer_handle =
1050 tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts,
1051 3 /* timer id */ ,
1052 expiration_time);
1053
1054 run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1);
1055
1056 after = clib_time_now (&tm->clib_time);
1057
1058 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1059 tm->triple_wheel.current_tick);
1060 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1061 (after - before),
1062 ((f64) adds + (f64) deletes +
1063 (f64) tm->triple_wheel.current_tick) / (after - before));
1064
1065 if (pool_elts (tm->test_elts))
1066 fformat (stdout, "Note: %d elements remain in pool\n",
1067 pool_elts (tm->test_elts));
1068
1069 /* *INDENT-OFF* */
1070 pool_foreach (e, tm->test_elts,
1071 ({
1072 fformat (stdout, "[%d] expected to expire %d\n",
1073 e - tm->test_elts,
1074 e->expected_to_expire);
1075 }));
1076 /* *INDENT-ON* */
1077
1078 pool_free (tm->test_elts);
1079 tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel);
1080 return 0;
1081}
1082
1083static clib_error_t *
1084test4_double_double (tw_timer_test_main_t * tm)
1085{
1086 u32 i;
1087 tw_timer_test_elt_t *e;
1088 u32 initial_wheel_offset;
1089 u32 expiration_time;
1090 u32 max_expiration_time = 0;
1091 u32 *deleted_indices = 0;
1092 u32 adds = 0, deletes = 0;
1093 f64 before, after;
1094
1095 clib_time_init (&tm->clib_time);
1096
1097 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1098 expired_timer_double_callback,
1099 1.0 /* timer interval */ , ~0);
1100 /* Prime offset */
1101 initial_wheel_offset = 0;
1102
1103 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
1104
1105 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
1106 tm->double_wheel.current_tick,
1107 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
1108 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
1109
1110 initial_wheel_offset = tm->double_wheel.current_tick;
1111
1112 fformat (stdout, "test timer which expires at 512 ticks\n");
1113
1114 before = clib_time_now (&tm->clib_time);
1115
1116 /* Prime the pump */
1117 for (i = 0; i < tm->ntimers; i++)
1118 {
1119 pool_get (tm->test_elts, e);
1120 memset (e, 0, sizeof (*e));
1121
1122 expiration_time = 512;
1123
1124 if (expiration_time > max_expiration_time)
1125 max_expiration_time = expiration_time;
1126
1127 e->expected_to_expire = expiration_time + initial_wheel_offset;
1128 e->stop_timer_handle =
1129 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
1130 14 /* timer id */ ,
1131 expiration_time);
1132 }
1133
1134 adds = 1;
1135
1136 vec_free (deleted_indices);
1137
1138 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
1139
1140 after = clib_time_now (&tm->clib_time);
1141
1142 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1143 tm->double_wheel.current_tick);
1144 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1145 (after - before),
1146 ((f64) adds + (f64) deletes +
1147 (f64) tm->double_wheel.current_tick) / (after - before));
1148
1149 if (pool_elts (tm->test_elts))
1150 fformat (stdout, "Note: %d elements remain in pool\n",
1151 pool_elts (tm->test_elts));
1152
1153 /* *INDENT-OFF* */
1154 pool_foreach (e, tm->test_elts,
1155 ({
1156 fformat (stdout, "[%d] expected to expire %d\n",
1157 e - tm->test_elts,
1158 e->expected_to_expire);
1159 }));
1160 /* *INDENT-ON* */
1161
1162 pool_free (tm->test_elts);
1163 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1164 return 0;
1165}
1166
1167static clib_error_t *
1168test5_double (tw_timer_test_main_t * tm)
1169{
1170 u32 i;
1171 tw_timer_test_elt_t *e;
1172 u32 initial_wheel_offset;
1173 u32 expiration_time;
1174 u32 max_expiration_time = 0;
1175 u32 adds = 0, deletes = 0;
1176 f64 before, after;
1177
1178 clib_time_init (&tm->clib_time);
1179
1180 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1181 expired_timer_double_callback,
1182 1.0 /* timer interval */ , ~0);
1183
1184 /* Prime offset */
1185 initial_wheel_offset = 7567;
1186
1187 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
1188
1189 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
1190 tm->double_wheel.current_tick,
1191 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
1192 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
1193
1194 initial_wheel_offset = tm->double_wheel.current_tick;
1195
1196 fformat (stdout,
1197 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
1198 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
1199
1200 before = clib_time_now (&tm->clib_time);
1201
1202 /* Prime the pump */
1203 for (i = 0; i < tm->ntimers; i++)
1204 {
1205 pool_get (tm->test_elts, e);
1206 memset (e, 0, sizeof (*e));
1207
1208 expiration_time = i + 1;
1209
1210 if (expiration_time > max_expiration_time)
1211 max_expiration_time = expiration_time;
1212
1213 e->expected_to_expire = expiration_time + initial_wheel_offset;
1214 e->stop_timer_handle =
1215 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
1216 14 /* timer id */ ,
1217 expiration_time);
1218 }
1219
1220 adds += i;
1221
1222 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
1223
1224 after = clib_time_now (&tm->clib_time);
1225
1226 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1227 tm->double_wheel.current_tick);
1228 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1229 (after - before),
1230 ((f64) adds + (f64) deletes +
1231 (f64) tm->double_wheel.current_tick) / (after - before));
1232
1233 if (pool_elts (tm->test_elts))
1234 fformat (stdout, "Note: %d elements remain in pool\n",
1235 pool_elts (tm->test_elts));
1236
1237 /* *INDENT-OFF* */
1238 pool_foreach (e, tm->test_elts,
1239 ({
1240 fformat (stdout, "[%d] expected to expire %d\n",
1241 e - tm->test_elts,
1242 e->expected_to_expire);
1243 }));
1244 /* *INDENT-ON* */
1245
1246 pool_free (tm->test_elts);
1247 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1248 return 0;
1249}
1250
1251static clib_error_t *
Dave Barach8e8f98c2017-02-03 11:58:53 -05001252timer_test_command_fn (tw_timer_test_main_t * tm, unformat_input_t * input)
1253{
1254
Florin Corasadb5bd52018-06-22 15:29:38 -07001255 int is_test1 = 0, is_updates = 0;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001256 int num_wheels = 1;
1257 int is_test2 = 0;
Dave Barach4af9ba12017-06-07 15:18:23 -04001258 int is_test3 = 0;
1259 int is_test4 = 0;
1260 int is_test5 = 0;
1261 int overflow = 0;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001262
1263 memset (tm, 0, sizeof (*tm));
1264 /* Default values */
1265 tm->ntimers = 100000;
Dave Barach4af9ba12017-06-07 15:18:23 -04001266 tm->seed = 0xDEADDABEB00BFACE;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001267 tm->niter = 1000;
1268 tm->ticks_per_iter = 727;
1269
1270 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1271 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001272 if (unformat (input, "seed %lld", &tm->seed))
Dave Barach8e8f98c2017-02-03 11:58:53 -05001273 ;
1274 else if (unformat (input, "test1"))
1275 is_test1 = 1;
1276 else if (unformat (input, "test2"))
1277 is_test2 = 1;
Dave Barach4af9ba12017-06-07 15:18:23 -04001278 else if (unformat (input, "overflow"))
1279 overflow = 1;
1280 else if (unformat (input, "lebron"))
1281 is_test3 = 1;
1282 else if (unformat (input, "wilt"))
1283 is_test4 = 1;
1284 else if (unformat (input, "linear"))
1285 is_test5 = 1;
Florin Corasadb5bd52018-06-22 15:29:38 -07001286 else if (unformat (input, "updates"))
1287 is_updates = 1;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001288 else if (unformat (input, "wheels %d", &num_wheels))
1289 ;
1290 else if (unformat (input, "ntimers %d", &tm->ntimers))
1291 ;
1292 else if (unformat (input, "niter %d", &tm->niter))
1293 ;
1294 else if (unformat (input, "ticks_per_iter %d", &tm->ticks_per_iter))
1295 ;
Dave Barach4af9ba12017-06-07 15:18:23 -04001296 else
1297 break;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001298 }
1299
Dave Barach4af9ba12017-06-07 15:18:23 -04001300 if (is_test1 + is_test2 + is_test3 + is_test4 + is_test5 == 0)
Dave Barach8e8f98c2017-02-03 11:58:53 -05001301 return clib_error_return (0, "No test specified [test1..n]");
1302
Dave Barach4af9ba12017-06-07 15:18:23 -04001303 if (num_wheels < 1 || num_wheels > 3)
Dave Barach8e8f98c2017-02-03 11:58:53 -05001304 return clib_error_return (0, "unsupported... 1 or 2 wheels only");
1305
1306 if (is_test1)
1307 {
1308 if (num_wheels == 1)
1309 return test1_single (tm);
1310 else
1311 return test1_double (tm);
1312 }
1313 if (is_test2)
1314 {
1315 if (num_wheels == 1)
1316 return test2_single (tm);
Dave Barach4af9ba12017-06-07 15:18:23 -04001317 else if (num_wheels == 2)
Florin Corasadb5bd52018-06-22 15:29:38 -07001318 if (is_updates)
1319 return test2_double_updates (tm);
1320 else
1321 return test2_double (tm);
Dave Barach4af9ba12017-06-07 15:18:23 -04001322 else if (num_wheels == 3)
1323 {
1324 if (overflow == 0)
1325 return test2_triple (tm);
1326 else
1327 return test2_triple_ov (tm);
1328 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001329 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001330 if (is_test3)
1331 return test3_triple_double (tm);
1332
1333 if (is_test4)
1334 return test4_double_double (tm);
1335
1336 if (is_test5)
1337 return test5_double (tm);
1338
Dave Barach8e8f98c2017-02-03 11:58:53 -05001339 /* NOTREACHED */
1340 return 0;
1341}
1342
1343#ifdef CLIB_UNIX
1344int
1345main (int argc, char *argv[])
1346{
1347 unformat_input_t i;
1348 clib_error_t *error;
1349 tw_timer_test_main_t *tm = &tw_timer_test_main;
1350
1351 clib_mem_init (0, 3ULL << 30);
1352
1353 unformat_init_command_line (&i, argv);
1354 error = timer_test_command_fn (tm, &i);
1355 unformat_free (&i);
1356
1357 if (error)
1358 {
1359 clib_error_report (error);
1360 return 1;
1361 }
1362 return 0;
1363}
1364#endif /* CLIB_UNIX */
1365
Dave Barach4af9ba12017-06-07 15:18:23 -04001366/* For debugging... */
1367int
1368pifi (void *p, u32 index)
1369{
1370 return pool_is_free_index (p, index);
1371}
1372
1373u32
1374vl (void *p)
1375{
1376 return vec_len (p);
1377}
1378
1379uword
1380pe (void *v)
1381{
1382 return (pool_elts (v));
1383}
1384
Dave Barach8e8f98c2017-02-03 11:58:53 -05001385/*
1386 * fd.io coding-style-patch-verification: ON
1387 *
1388 * Local Variables:
1389 * eval: (c-set-style "gnu")
1390 * End:
1391 */