API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_bench_timer.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2023-2026 Nokia
3 */
4
13#ifndef _GNU_SOURCE
14#define _GNU_SOURCE /* Needed for sigaction */
15#endif
16
17#include <odp_api.h>
18#include <odp/helper/odph_api.h>
19
20#include <bench_common.h>
21#include <export_results.h>
22
23#include <getopt.h>
24#include <inttypes.h>
25#include <signal.h>
26#include <stdlib.h>
27#include <unistd.h>
28
29/* Number of API function calls per test case */
30#define REPEAT_COUNT 1000
31
32/* Default number of rounds per test case */
33#define ROUNDS 1000u
34
35/* User area size in bytes */
36#define UAREA_SIZE 8
37
38/* Timer duration in nsec */
39#define TIMER_NSEC 50000000
40
41/* Maximum number of results to be held */
42#define TEST_MAX_BENCH 20
43
44#define BENCH_INFO(run_fn, init_fn, term_fn) \
45 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn}
46
47#define BENCH_INFO_TM(run_fn, init_fn, term_fn) \
48 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn}
49
50typedef enum {
51 M_TPUT,
52 M_LATENCY
53} meas_mode_t;
54
55typedef struct {
56 /* Command line options */
57 struct {
58 /* Clock source to be used */
59 int clk_src;
60 /* Measure time vs CPU cycles */
61 int time;
62 /* Benchmark index to run indefinitely */
63 int bench_idx;
64 /* Rounds per test case */
65 uint32_t rounds;
66 /* Measurement mode */
67 meas_mode_t mode;
68
69 } opt;
70
71 /* Common benchmark suite data */
72 struct {
73 union {
74 /* Basic suite for avg */
75 bench_suite_t b;
76 /* TM suite for min/max/avg */
77 bench_tm_suite_t t;
78 };
79
80 /* Loop breaker */
81 odp_atomic_u32_t *exit;
82 /* Pointer to suite return value */
83 int *retval;
84 /* Suite args */
85 void *args;
86 /* Suite runner */
87 int (*suite_fn)(void *args);
88 /* Data exporter */
89 int (*export_fn)(void *data);
90 /* Dummy storage */
91 uint64_t dummy;
92 } suite;
93
94 odp_timer_start_t start_param;
95 odp_timer_pool_t timer_pool;
96 odp_timer_t timer;
97 odp_queue_t queue;
98 odp_pool_t pool;
99 odp_timeout_t timeout;
100 odp_event_t event;
101 uint64_t timer_nsec;
102 uint64_t tick;
103 uint64_t nsec;
104 double tick_hz;
105 int plain_queue;
106
107 /* Test case input / output data */
108 uint64_t a1[REPEAT_COUNT];
109 odp_event_t ev[REPEAT_COUNT];
110 odp_timeout_t tmo[REPEAT_COUNT];
111 odp_timer_t tim_src[REPEAT_COUNT];
112 odp_timer_t tim_dst[REPEAT_COUNT];
113
114 /* CPU mask as string */
115 char cpumask_str[ODP_CPUMASK_STR_SIZE];
116
117 /* Array for storing results */
118 union{
119 /* Basic suite results */
120 double b[TEST_MAX_BENCH];
121 /* TM suite results */
122 bench_tm_result_t t[TEST_MAX_BENCH];
123 } result;
124
125} gbl_args_t;
126
127static gbl_args_t *gbl_args;
128
129static void sig_handler(int signo ODP_UNUSED)
130{
131 if (gbl_args == NULL)
132 return;
133 odp_atomic_store_u32(gbl_args->suite.exit, 1);
134}
135
136static int setup_sig_handler(void)
137{
138 struct sigaction action;
139
140 memset(&action, 0, sizeof(action));
141 action.sa_handler = sig_handler;
142
143 /* No additional signals blocked. By default, the signal which triggered
144 * the handler is blocked. */
145 if (sigemptyset(&action.sa_mask))
146 return -1;
147
148 if (sigaction(SIGINT, &action, NULL))
149 return -1;
150
151 return 0;
152}
153
154static void cancel_timers(void)
155{
156 odp_timer_t *tim = gbl_args->tim_src;
157 odp_event_t ev;
158 int ret;
159
160 for (int i = 0; i < REPEAT_COUNT; i++) {
161 ret = odp_timer_cancel(tim[i], &ev);
162
163 if (ret == ODP_TIMER_FAIL)
164 ODPH_ABORT("Failed to cancel timer, ret: %d, index: %d\n", ret, i);
165 }
166}
167
168static void start_timers(void)
169{
170 odp_timer_t *tim = gbl_args->tim_src;
171 const odp_timer_start_t *start = &gbl_args->start_param;
172 int ret;
173
174 for (int i = 0; i < REPEAT_COUNT; i++) {
175 ret = odp_timer_start(tim[i], start);
176
177 if (ret != ODP_TIMER_SUCCESS)
178 ODPH_ABORT("Failed to start timer, ret: %d, index: %d\n", ret, i);
179 }
180}
181
182static int timer_current_tick(void)
183{
184 int i;
185 odp_timer_pool_t timer_pool = gbl_args->timer_pool;
186 uint64_t *a1 = gbl_args->a1;
187
188 for (i = 0; i < REPEAT_COUNT; i++)
189 a1[i] = odp_timer_current_tick(timer_pool);
190
191 return i;
192}
193
194static int timer_current_tick_tm(bench_tm_result_t *res, int repeat_count)
195{
196 int i;
197 odp_timer_pool_t timer_pool = gbl_args->timer_pool;
198 uint64_t *a1 = gbl_args->a1;
199 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_current_tick()");
200 bench_tm_stamp_t s1, s2;
201
202 for (i = 0; i < repeat_count; i++) {
203 bench_tm_now(res, &s1);
204 a1[i] = odp_timer_current_tick(timer_pool);
205 bench_tm_now(res, &s2);
206 bench_tm_func_record(&s2, &s1, res, id1);
207 }
208
209 return i;
210}
211
212static int timer_tick_to_ns(void)
213{
214 int i;
215 odp_timer_pool_t timer_pool = gbl_args->timer_pool;
216 uint64_t *a1 = gbl_args->a1;
217 uint64_t tick = gbl_args->tick;
218
219 for (i = 0; i < REPEAT_COUNT; i++)
220 a1[i] = odp_timer_tick_to_ns(timer_pool, tick);
221
222 return i;
223}
224
225static int timer_tick_to_ns_tm(bench_tm_result_t *res, int repeat_count)
226{
227 int i;
228 odp_timer_pool_t timer_pool = gbl_args->timer_pool;
229 uint64_t *a1 = gbl_args->a1;
230 uint64_t tick = gbl_args->tick;
231 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_tick_to_ns()");
232 bench_tm_stamp_t s1, s2;
233
234 for (i = 0; i < repeat_count; i++) {
235 bench_tm_now(res, &s1);
236 a1[i] = odp_timer_tick_to_ns(timer_pool, tick);
237 bench_tm_now(res, &s2);
238 bench_tm_func_record(&s2, &s1, res, id1);
239 }
240
241 return i;
242}
243
244static int timer_ns_to_tick(void)
245{
246 int i;
247 odp_timer_pool_t timer_pool = gbl_args->timer_pool;
248 uint64_t *a1 = gbl_args->a1;
249 uint64_t nsec = gbl_args->nsec;
250
251 for (i = 0; i < REPEAT_COUNT; i++)
252 a1[i] = odp_timer_ns_to_tick(timer_pool, nsec);
253
254 return i;
255}
256
257static int timer_ns_to_tick_tm(bench_tm_result_t *res, int repeat_count)
258{
259 int i;
260 odp_timer_pool_t timer_pool = gbl_args->timer_pool;
261 uint64_t *a1 = gbl_args->a1;
262 uint64_t nsec = gbl_args->nsec;
263 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_ns_to_tick()");
264 bench_tm_stamp_t s1, s2;
265
266 for (i = 0; i < repeat_count; i++) {
267 bench_tm_now(res, &s1);
268 a1[i] = odp_timer_ns_to_tick(timer_pool, nsec);
269 bench_tm_now(res, &s2);
270 bench_tm_func_record(&s2, &s1, res, id1);
271 }
272
273 return i;
274}
275
276static int timeout_to_event(void)
277{
278 int i;
279 odp_event_t *ev = gbl_args->ev;
280 odp_timeout_t timeout = gbl_args->timeout;
281
282 for (i = 0; i < REPEAT_COUNT; i++)
283 ev[i] = odp_timeout_to_event(timeout);
284
285 gbl_args->suite.dummy += odp_event_to_u64(ev[0]);
286
287 return i;
288}
289
290static int timeout_to_event_tm(bench_tm_result_t *res, int repeat_count)
291{
292 int i;
293 odp_event_t *ev = gbl_args->ev;
294 odp_timeout_t timeout = gbl_args->timeout;
295 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_to_event()");
296 bench_tm_stamp_t s1, s2;
297
298 for (i = 0; i < repeat_count; i++) {
299 bench_tm_now(res, &s1);
300 ev[i] = odp_timeout_to_event(timeout);
301 bench_tm_now(res, &s2);
302 bench_tm_func_record(&s2, &s1, res, id1);
303 }
304
305 gbl_args->suite.dummy += odp_event_to_u64(ev[0]);
306
307 return i;
308}
309
310static int timeout_from_event(void)
311{
312 int i;
313 odp_event_t ev = gbl_args->event;
314 odp_timeout_t *tmo = gbl_args->tmo;
315
316 for (i = 0; i < REPEAT_COUNT; i++)
317 tmo[i] = odp_timeout_from_event(ev);
318
319 gbl_args->suite.dummy += odp_timeout_to_u64(tmo[0]);
320
321 return i;
322}
323
324static int timeout_from_event_tm(bench_tm_result_t *res, int repeat_count)
325{
326 int i;
327 odp_event_t ev = gbl_args->event;
328 odp_timeout_t *tmo = gbl_args->tmo;
329 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_from_event()");
330 bench_tm_stamp_t s1, s2;
331
332 for (i = 0; i < repeat_count; i++) {
333 bench_tm_now(res, &s1);
334 tmo[i] = odp_timeout_from_event(ev);
335 bench_tm_now(res, &s2);
336 bench_tm_func_record(&s2, &s1, res, id1);
337 }
338
339 gbl_args->suite.dummy += odp_timeout_to_u64(tmo[0]);
340
341 return i;
342}
343
344static int timeout_timer(void)
345{
346 int i;
347 odp_timeout_t timeout = gbl_args->timeout;
348 odp_timer_t *tim = gbl_args->tim_dst;
349
350 for (i = 0; i < REPEAT_COUNT; i++)
351 tim[i] = odp_timeout_timer(timeout);
352
353 gbl_args->suite.dummy += odp_timer_to_u64(tim[0]);
354
355 return i;
356}
357
358static int timeout_timer_tm(bench_tm_result_t *res, int repeat_count)
359{
360 int i;
361 odp_timeout_t timeout = gbl_args->timeout;
362 odp_timer_t *tim = gbl_args->tim_dst;
363 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_timer()");
364 bench_tm_stamp_t s1, s2;
365
366 for (i = 0; i < repeat_count; i++) {
367 bench_tm_now(res, &s1);
368 tim[i] = odp_timeout_timer(timeout);
369 bench_tm_now(res, &s2);
370 bench_tm_func_record(&s2, &s1, res, id1);
371 }
372
373 gbl_args->suite.dummy += odp_timer_to_u64(tim[0]);
374
375 return i;
376}
377
378static int timeout_tick(void)
379{
380 int i;
381 odp_timeout_t timeout = gbl_args->timeout;
382 uint64_t *a1 = gbl_args->a1;
383
384 for (i = 0; i < REPEAT_COUNT; i++)
385 a1[i] = odp_timeout_tick(timeout);
386
387 return i;
388}
389
390static int timeout_tick_tm(bench_tm_result_t *res, int repeat_count)
391{
392 int i;
393 odp_timeout_t timeout = gbl_args->timeout;
394 uint64_t *a1 = gbl_args->a1;
395 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_tick()");
396 bench_tm_stamp_t s1, s2;
397
398 for (i = 0; i < repeat_count; i++) {
399 bench_tm_now(res, &s1);
400 a1[i] = odp_timeout_tick(timeout);
401 bench_tm_now(res, &s2);
402 bench_tm_func_record(&s2, &s1, res, id1);
403 }
404
405 return i;
406}
407
408static int timeout_user_ptr(void)
409{
410 int i;
411 odp_timeout_t timeout = gbl_args->timeout;
412 uint64_t *a1 = gbl_args->a1;
413
414 for (i = 0; i < REPEAT_COUNT; i++)
415 a1[i] = (uintptr_t)odp_timeout_user_ptr(timeout);
416
417 return i;
418}
419
420static int timeout_user_ptr_tm(bench_tm_result_t *res, int repeat_count)
421{
422 int i;
423 odp_timeout_t timeout = gbl_args->timeout;
424 uint64_t *a1 = gbl_args->a1;
425 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_user_ptr()");
426 bench_tm_stamp_t s1, s2;
427
428 for (i = 0; i < repeat_count; i++) {
429 bench_tm_now(res, &s1);
430 a1[i] = (uintptr_t)odp_timeout_user_ptr(timeout);
431 bench_tm_now(res, &s2);
432 bench_tm_func_record(&s2, &s1, res, id1);
433 }
434
435 return i;
436}
437
438static int timeout_user_area(void)
439{
440 int i;
441 odp_timeout_t timeout = gbl_args->timeout;
442 uint64_t *a1 = gbl_args->a1;
443
444 for (i = 0; i < REPEAT_COUNT; i++)
445 a1[i] = (uintptr_t)odp_timeout_user_area(timeout);
446
447 return i;
448}
449
450static int timeout_user_area_tm(bench_tm_result_t *res, int repeat_count)
451{
452 int i;
453 odp_timeout_t timeout = gbl_args->timeout;
454 uint64_t *a1 = gbl_args->a1;
455 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_user_area()");
456 bench_tm_stamp_t s1, s2;
457
458 for (i = 0; i < repeat_count; i++) {
459 bench_tm_now(res, &s1);
460 a1[i] = (uintptr_t)odp_timeout_user_area(timeout);
461 bench_tm_now(res, &s2);
462 bench_tm_func_record(&s2, &s1, res, id1);
463 }
464
465 return i;
466}
467
468static int timeout_is_periodic(void)
469{
470 int i;
471 odp_timeout_t timeout = gbl_args->timeout;
472 uint64_t *a1 = gbl_args->a1;
473
474 for (i = 0; i < REPEAT_COUNT; i++)
475 a1[i] = odp_timeout_is_periodic(timeout);
476
477 return i;
478}
479
480static int timeout_is_periodic_tm(bench_tm_result_t *res, int repeat_count)
481{
482 int i;
483 odp_timeout_t timeout = gbl_args->timeout;
484 uint64_t *a1 = gbl_args->a1;
485 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_is_periodic()");
486 bench_tm_stamp_t s1, s2;
487
488 for (i = 0; i < repeat_count; i++) {
489 bench_tm_now(res, &s1);
490 a1[i] = odp_timeout_is_periodic(timeout);
491 bench_tm_now(res, &s2);
492 bench_tm_func_record(&s2, &s1, res, id1);
493 }
494
495 return i;
496}
497
498static int timeout_to_u64(void)
499{
500 int i;
501 odp_timeout_t timeout = gbl_args->timeout;
502 uint64_t *a1 = gbl_args->a1;
503
504 for (i = 0; i < REPEAT_COUNT; i++)
505 a1[i] = odp_timeout_to_u64(timeout);
506
507 return i;
508}
509
510static int timeout_to_u64_tm(bench_tm_result_t *res, int repeat_count)
511{
512 int i;
513 odp_timeout_t timeout = gbl_args->timeout;
514 uint64_t *a1 = gbl_args->a1;
515 const uint8_t id1 = bench_tm_func_register(res, "odp_timeout_to_u64()");
516 bench_tm_stamp_t s1, s2;
517
518 for (i = 0; i < repeat_count; i++) {
519 bench_tm_now(res, &s1);
520 a1[i] = odp_timeout_to_u64(timeout);
521 bench_tm_now(res, &s2);
522 bench_tm_func_record(&s2, &s1, res, id1);
523 }
524
525 return i;
526}
527
528static int timer_to_u64(void)
529{
530 int i;
531 odp_timer_t timer = gbl_args->timer;
532 uint64_t *a1 = gbl_args->a1;
533
534 for (i = 0; i < REPEAT_COUNT; i++)
535 a1[i] = odp_timer_to_u64(timer);
536
537 return i;
538}
539
540static int timer_to_u64_tm(bench_tm_result_t *res, int repeat_count)
541{
542 int i;
543 odp_timer_t timer = gbl_args->timer;
544 uint64_t *a1 = gbl_args->a1;
545 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_to_u64()");
546 bench_tm_stamp_t s1, s2;
547
548 for (i = 0; i < repeat_count; i++) {
549 bench_tm_now(res, &s1);
550 a1[i] = odp_timer_to_u64(timer);
551 bench_tm_now(res, &s2);
552 bench_tm_func_record(&s2, &s1, res, id1);
553 }
554
555 return i;
556}
557
558static int timer_pool_to_u64(void)
559{
560 int i;
561 odp_timer_pool_t tp = gbl_args->timer_pool;
562 uint64_t *a1 = gbl_args->a1;
563
564 for (i = 0; i < REPEAT_COUNT; i++)
565 a1[i] = odp_timer_pool_to_u64(tp);
566
567 return i;
568}
569
570static int timer_pool_to_u64_tm(bench_tm_result_t *res, int repeat_count)
571{
572 int i;
573 odp_timer_pool_t tp = gbl_args->timer_pool;
574 uint64_t *a1 = gbl_args->a1;
575 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_pool_to_u64()");
576 bench_tm_stamp_t s1, s2;
577
578 for (i = 0; i < repeat_count; i++) {
579 bench_tm_now(res, &s1);
580 a1[i] = odp_timer_pool_to_u64(tp);
581 bench_tm_now(res, &s2);
582 bench_tm_func_record(&s2, &s1, res, id1);
583 }
584
585 return i;
586}
587
588static int timer_start(void)
589{
590 int i, ret;
591 odp_timer_t *tim = gbl_args->tim_src;
592 const odp_timer_start_t *start = &gbl_args->start_param;
593
594 for (i = 0; i < REPEAT_COUNT; i++) {
595 ret = odp_timer_start(tim[i], start);
596
597 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
598 }
599
600 return i;
601}
602
603static int timer_start_tm(bench_tm_result_t *res, int repeat_count)
604{
605 int i, ret;
606 odp_timer_t *tim = gbl_args->tim_src;
607 const odp_timer_start_t *start = &gbl_args->start_param;
608 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_start()");
609 bench_tm_stamp_t s1, s2;
610
611 for (i = 0; i < repeat_count; i++) {
612 bench_tm_now(res, &s1);
613 ret = odp_timer_start(tim[i], start);
614
615 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
616
617 bench_tm_now(res, &s2);
618 bench_tm_func_record(&s2, &s1, res, id1);
619 }
620
621 return i;
622}
623
624static int timer_cancel(void)
625{
626 int i, ret;
627 odp_timer_t *tim = gbl_args->tim_src;
628 odp_event_t ev;
629
630 for (i = 0; i < REPEAT_COUNT; i++) {
631 ret = odp_timer_cancel(tim[i], &ev);
632
633 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
634 }
635
636 return i;
637}
638
639static int timer_cancel_tm(bench_tm_result_t *res, int repeat_count)
640{
641 int i, ret;
642 odp_timer_t *tim = gbl_args->tim_src;
643 odp_event_t ev;
644 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_cancel()");
645 bench_tm_stamp_t s1, s2;
646
647 for (i = 0; i < repeat_count; i++) {
648 bench_tm_now(res, &s1);
649 ret = odp_timer_cancel(tim[i], &ev);
650
651 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
652
653 bench_tm_now(res, &s2);
654 bench_tm_func_record(&s2, &s1, res, id1);
655 }
656
657 return i;
658}
659
660static int timer_start_cancel(void)
661{
662 int i, ret;
663 odp_timer_t *tim = gbl_args->tim_src;
664 const odp_timer_start_t *start = &gbl_args->start_param;
665 odp_event_t ev;
666
667 for (i = 0; i < REPEAT_COUNT; i++) {
668 ret = odp_timer_start(tim[i], start);
669
670 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
671
672 ret = odp_timer_cancel(tim[i], &ev);
673
674 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
675 }
676
677 return i;
678}
679
680static int timer_start_cancel_tm(bench_tm_result_t *res, int repeat_count)
681{
682 int i, ret;
683 odp_timer_t *tim = gbl_args->tim_src;
684 const odp_timer_start_t *start = &gbl_args->start_param;
685 odp_event_t ev;
686 const uint8_t id1 = bench_tm_func_register(res, "odp_timer_start()/_cancel()");
687 bench_tm_stamp_t s1, s2;
688
689 for (i = 0; i < repeat_count; i++) {
690 bench_tm_now(res, &s1);
691 ret = odp_timer_start(tim[i], start);
692
693 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
694
695 ret = odp_timer_cancel(tim[i], &ev);
696
697 ODPH_ASSERT(ret == ODP_TIMER_SUCCESS);
698
699 bench_tm_now(res, &s2);
700 bench_tm_func_record(&s2, &s1, res, id1);
701 }
702
703 return i;
704}
705
706static int bench_timer_tm_export(void *data)
707{
708 gbl_args_t *gbl_args = data;
709 bench_tm_result_t *res;
710 uint64_t num;
711 int ret = 0;
712 const char *unit = gbl_args->opt.time ? "nsec" : "cpu cycles";
713
714 if (test_common_write("function name,min %s per function call,"
715 "average %s per function call,"
716 "max %s per function call\n", unit, unit, unit)) {
717 ret = -1;
718 goto exit;
719 }
720
721 for (uint32_t i = 0; i < gbl_args->suite.t.num_bench; i++) {
722 res = &gbl_args->suite.t.result[i];
723
724 for (int j = 0; j < res->num; j++) {
725 num = res->func[j].num ? res->func[j].num : 1;
726 if (test_common_write("%s,%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
727 res->func[j].name,
728 bench_tm_to_u64(res, &res->func[j].min),
729 bench_tm_to_u64(res, &res->func[j].tot) / num,
730 bench_tm_to_u64(res, &res->func[j].max))) {
731 ret = -1;
732 goto exit;
733 }
734 }
735 }
736
737exit:
738 test_common_write_term();
739
740 return ret;
741}
742
743static int bench_timer_export(void *data)
744{
745 gbl_args_t *gbl_args = data;
746 int ret = 0;
747
748 if (test_common_write("%s", gbl_args->opt.time ?
749 "function name,average nsec per function call\n" :
750 "function name,average cpu cycles per function call\n")) {
751 ret = -1;
752 goto exit;
753 }
754
755 for (int i = 0; i < gbl_args->suite.b.num_bench; i++) {
756 if (test_common_write("odp_%s,%f\n",
757 gbl_args->suite.b.bench[i].name,
758 gbl_args->suite.b.result[i])) {
759 ret = -1;
760 goto exit;
761 }
762 }
763
764exit:
765 test_common_write_term();
766
767 return ret;
768}
769
770bench_info_t test_suite[] = {
771 BENCH_INFO(timer_current_tick, NULL, NULL),
772 BENCH_INFO(timer_tick_to_ns, NULL, NULL),
773 BENCH_INFO(timer_ns_to_tick, NULL, NULL),
774 BENCH_INFO(timeout_to_event, NULL, NULL),
775 BENCH_INFO(timeout_from_event, NULL, NULL),
776 BENCH_INFO(timeout_timer, NULL, NULL),
777 BENCH_INFO(timeout_tick, NULL, NULL),
778 BENCH_INFO(timeout_user_ptr, NULL, NULL),
779 BENCH_INFO(timeout_user_area, NULL, NULL),
780 BENCH_INFO(timeout_is_periodic, NULL, NULL),
781 BENCH_INFO(timeout_to_u64, NULL, NULL),
782 BENCH_INFO(timer_to_u64, NULL, NULL),
783 BENCH_INFO(timer_pool_to_u64, NULL, NULL),
784 BENCH_INFO(timer_start, NULL, cancel_timers),
785 BENCH_INFO(timer_cancel, start_timers, NULL),
786 BENCH_INFO(timer_start_cancel, NULL, NULL),
787};
788
789ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite) < TEST_MAX_BENCH,
790 "Result array is too small to hold all the results");
791
792bench_tm_info_t test_suite_tm[] = {
793 BENCH_INFO_TM(timer_current_tick_tm, NULL, NULL),
794 BENCH_INFO_TM(timer_tick_to_ns_tm, NULL, NULL),
795 BENCH_INFO_TM(timer_ns_to_tick_tm, NULL, NULL),
796 BENCH_INFO_TM(timeout_to_event_tm, NULL, NULL),
797 BENCH_INFO_TM(timeout_from_event_tm, NULL, NULL),
798 BENCH_INFO_TM(timeout_timer_tm, NULL, NULL),
799 BENCH_INFO_TM(timeout_tick_tm, NULL, NULL),
800 BENCH_INFO_TM(timeout_user_ptr_tm, NULL, NULL),
801 BENCH_INFO_TM(timeout_user_area_tm, NULL, NULL),
802 BENCH_INFO_TM(timeout_is_periodic_tm, NULL, NULL),
803 BENCH_INFO_TM(timeout_to_u64_tm, NULL, NULL),
804 BENCH_INFO_TM(timer_to_u64_tm, NULL, NULL),
805 BENCH_INFO_TM(timer_pool_to_u64_tm, NULL, NULL),
806 BENCH_INFO_TM(timer_start_tm, NULL, cancel_timers),
807 BENCH_INFO_TM(timer_cancel_tm, start_timers, NULL),
808 BENCH_INFO_TM(timer_start_cancel_tm, NULL, NULL),
809};
810
811ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite_tm) < TEST_MAX_BENCH,
812 "Result array is too small to hold all the results");
813
814/* Print usage information */
815static void usage(void)
816{
817 printf("\n"
818 "ODP timer API micro benchmarks\n"
819 "\n"
820 "Options:\n"
821 " -s, --clk_src Clock source select (default 0):\n"
822 " 0: ODP_CLOCK_DEFAULT\n"
823 " 1: ODP_CLOCK_SRC_1, ...\n"
824 " -t, --time <opt> Time measurement. 0: measure CPU cycles (default), 1: measure time\n"
825 " -i, --index <idx> Benchmark index to run indefinitely.\n"
826 " -r, --rounds <num> Run each test case 'num' times (default %u).\n"
827 " -m, --mode <mode> Measurement mode. 0: measure throughput, track average execution\n"
828 " time (default), 1: measure latency, track function minimum and\n"
829 " maximum in addition to average execution time.\n"
830 " -h, --help Display help and exit.\n\n"
831 "\n", ROUNDS);
832}
833
834/* Parse command line arguments */
835static int parse_args(int argc, char *argv[])
836{
837 int opt;
838 static const struct option longopts[] = {
839 {"clk_src", required_argument, NULL, 's'},
840 {"time", required_argument, NULL, 't'},
841 {"index", required_argument, NULL, 'i'},
842 {"rounds", required_argument, NULL, 'r'},
843 {"mode", required_argument, NULL, 'm'},
844 {"help", no_argument, NULL, 'h'},
845 {NULL, 0, NULL, 0}
846 };
847
848 static const char *shortopts = "s:t:i:r:m:h";
849
850 gbl_args->opt.clk_src = ODP_CLOCK_DEFAULT;
851 gbl_args->opt.time = 0; /* Measure CPU cycles */
852 gbl_args->opt.bench_idx = 0; /* Run all benchmarks */
853 gbl_args->opt.rounds = ROUNDS;
854 gbl_args->opt.mode = M_TPUT;
855
856 while (1) {
857 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
858
859 if (opt == -1)
860 break; /* No more options */
861
862 switch (opt) {
863 case 's':
864 gbl_args->opt.clk_src = atoi(optarg);
865 break;
866 case 't':
867 gbl_args->opt.time = atoi(optarg);
868 break;
869 case 'i':
870 gbl_args->opt.bench_idx = atoi(optarg);
871 break;
872 case 'r':
873 gbl_args->opt.rounds = atoi(optarg);
874 break;
875 case 'm':
876 gbl_args->opt.mode = atoi(optarg);
877 break;
878 case 'h':
879 usage();
880 return 1;
881 default:
882 ODPH_ERR("Bad option. Use -h for help.\n");
883 return -1;
884 }
885 }
886
887 if (gbl_args->opt.rounds < 1) {
888 ODPH_ERR("Invalid test cycle repeat count: %u\n", gbl_args->opt.rounds);
889 return -1;
890 }
891
892 if (gbl_args->opt.bench_idx < 0 ||
893 gbl_args->opt.bench_idx > (int)ODPH_ARRAY_SIZE(test_suite)) {
894 ODPH_ERR("Bad bench index %i\n", gbl_args->opt.bench_idx);
895 return -1;
896 }
897
898 if (gbl_args->opt.mode != M_TPUT && gbl_args->opt.mode != M_LATENCY) {
899 printf("Invalid measurement mode: %d\n", gbl_args->opt.mode);
900 exit(EXIT_FAILURE);
901 }
902
903 optind = 1; /* Reset 'extern optind' from the getopt lib */
904
905 return 0;
906}
907
908/* Print system and application info */
909static void print_info(void)
910{
912
913 printf("\n"
914 "odp_bench_timer options\n"
915 "-----------------------\n");
916
917 printf("CPU mask: %s\n", gbl_args->cpumask_str);
918 printf("Clock source: %i\n", gbl_args->opt.clk_src);
919 printf("Measurement unit: %s\n", gbl_args->opt.time ? "nsec" : "CPU cycles");
920 printf("Test rounds: %u\n", gbl_args->opt.rounds);
921 printf("Timer duration: %" PRIu64 " nsec\n", gbl_args->timer_nsec);
922 printf("Timer tick freq: %.2f Hz\n", gbl_args->tick_hz);
923 printf("Measurement mode: %s\n", gbl_args->opt.mode == M_TPUT ? "throughput" : "latency");
924 printf("\n");
925}
926
927static int create_timers(void)
928{
929 odp_pool_capability_t pool_capa;
930 odp_timer_capability_t timer_capa;
931 odp_timer_clk_src_t clk_src;
932 odp_timer_pool_param_t tp_param;
934 odp_pool_t pool;
935 odp_pool_param_t pool_param;
936 odp_timeout_t tmo;
937 odp_queue_param_t queue_param;
938 odp_queue_t queue;
939 odp_timer_t timer, *tim_src = gbl_args->tim_src;
940 uint64_t t1, t2, diff, tick1, tick2;
941 const uint32_t num_timers = REPEAT_COUNT + 1;
942
943 if (odp_pool_capability(&pool_capa)) {
944 ODPH_ERR("Pool capa failed\n");
945 return -1;
946 }
947
948 clk_src = gbl_args->opt.clk_src;
949 if (odp_timer_capability(clk_src, &timer_capa)) {
950 ODPH_ERR("Timer capa failed\n");
951 return -1;
952 }
953
954 if (timer_capa.max_timers != 0 && timer_capa.max_timers < num_timers) {
955 ODPH_ERR("Not enough timers supported\n");
956 return -1;
957 }
958
959 odp_timer_pool_param_init(&tp_param);
960 tp_param.clk_src = clk_src;
961 tp_param.res_ns = timer_capa.max_res.res_ns;
962 tp_param.min_tmo = timer_capa.max_res.min_tmo;
963 tp_param.max_tmo = timer_capa.max_res.max_tmo;
964 tp_param.num_timers = num_timers;
965
966 tp = odp_timer_pool_create("bench_timer", &tp_param);
967
968 if (tp == ODP_TIMER_POOL_INVALID) {
969 ODPH_ERR("Timer pool create failed\n");
970 return -1;
971 }
972
973 if (odp_timer_pool_start_multi(&tp, 1) != 1) {
974 ODPH_ERR("Timer pool start failed\n");
975 return -1;
976 }
977
978 gbl_args->timer_pool = tp;
979
980 gbl_args->timer_nsec = TIMER_NSEC;
981 if (TIMER_NSEC < tp_param.min_tmo)
982 gbl_args->timer_nsec = tp_param.min_tmo;
983 else if (TIMER_NSEC > tp_param.max_tmo)
984 gbl_args->timer_nsec = tp_param.max_tmo;
985
986 odp_pool_param_init(&pool_param);
987 pool_param.type = ODP_POOL_TIMEOUT;
988 pool_param.tmo.num = 10;
989 pool_param.tmo.uarea_size = UAREA_SIZE;
990 if (UAREA_SIZE > pool_capa.tmo.max_uarea_size)
991 pool_param.tmo.uarea_size = pool_capa.tmo.max_uarea_size;
992
993 pool = odp_pool_create("bench_timer", &pool_param);
994
995 if (pool == ODP_POOL_INVALID) {
996 ODPH_ERR("Timeout pool create failed\n");
997 return -1;
998 }
999
1000 gbl_args->pool = pool;
1001
1002 tmo = odp_timeout_alloc(pool);
1003
1004 if (tmo == ODP_TIMEOUT_INVALID) {
1005 ODPH_ERR("Timeout alloc failed\n");
1006 return -1;
1007 }
1008
1009 gbl_args->timeout = tmo;
1010 gbl_args->tick = odp_timer_current_tick(tp);
1011 gbl_args->nsec = odp_timer_tick_to_ns(tp, gbl_args->tick);
1012
1013 /* Measure timer tick frequency for test information */
1015 tick1 = odp_timer_current_tick(tp);
1016
1018
1019 tick2 = odp_timer_current_tick(tp);
1021 diff = t2 - t1;
1022
1023 if (diff)
1024 gbl_args->tick_hz = (tick2 - tick1) / ((double)diff / ODP_TIME_SEC_IN_NS);
1025
1026 odp_queue_param_init(&queue_param);
1027 queue_param.type = ODP_QUEUE_TYPE_SCHED;
1028 queue_param.sched.prio = odp_schedule_default_prio();
1029 queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;
1030 queue_param.sched.group = ODP_SCHED_GROUP_ALL;
1031
1032 if (timer_capa.queue_type_sched == 0) {
1033 queue_param.type = ODP_QUEUE_TYPE_PLAIN;
1034 gbl_args->plain_queue = 1;
1035 }
1036
1037 queue = odp_queue_create("bench_timer", &queue_param);
1038 if (queue == ODP_QUEUE_INVALID) {
1039 ODPH_ERR("Queue create failed\n");
1040 return -1;
1041 }
1042
1043 gbl_args->queue = queue;
1044
1045 timer = odp_timer_alloc(tp, queue, (void *)(uintptr_t)0xdeadbeef);
1046 if (timer == ODP_TIMER_INVALID) {
1047 ODPH_ERR("Timer alloc failed\n");
1048 return -1;
1049 }
1050
1051 gbl_args->timer = timer;
1052
1053 for (int i = 0; i < REPEAT_COUNT; i++) {
1054 tim_src[i] = odp_timer_alloc(tp, queue, NULL);
1055
1056 if (tim_src[i] == ODP_TIMER_INVALID) {
1057 ODPH_ERR("Timer alloc failed\n");
1058 return -1;
1059 }
1060 }
1061
1062 return 0;
1063}
1064
1065static int wait_timer(void)
1066{
1067 odp_timer_start_t *start_param = &gbl_args->start_param;
1068 odp_timer_t timer = gbl_args->timer;
1069 odp_timer_pool_t tp = gbl_args->timer_pool;
1070 uint64_t wait_nsec = 2 * gbl_args->timer_nsec;
1071 uint64_t sched_wait = odp_schedule_wait_time(wait_nsec);
1072 odp_event_t ev;
1073 uint64_t start;
1074
1075 start_param->tick_type = ODP_TIMER_TICK_REL;
1076 start_param->tick = odp_timer_ns_to_tick(tp, gbl_args->timer_nsec);
1077 start_param->tmo_ev = odp_timeout_to_event(gbl_args->timeout);
1078
1079 if (odp_timer_start(timer, start_param) != ODP_TIMER_SUCCESS) {
1080 ODPH_ERR("Timer start failed\n");
1081 return -1;
1082 }
1083
1084 gbl_args->timeout = ODP_TIMEOUT_INVALID;
1085 gbl_args->event = ODP_EVENT_INVALID;
1086
1087 /* Wait for timeout */
1088 if (gbl_args->plain_queue) {
1089 start = odp_time_global_ns();
1090 while (1) {
1091 ev = odp_queue_deq(gbl_args->queue);
1092
1093 if (ev != ODP_EVENT_INVALID)
1094 break;
1095
1096 if ((odp_time_global_ns() - start) > wait_nsec) {
1097 ODPH_ERR("Timeout event missing\n");
1098 return -1;
1099 }
1100 }
1101
1102 gbl_args->event = ev;
1103 } else {
1104 ev = odp_schedule(NULL, sched_wait);
1105
1106 if (ev == ODP_EVENT_INVALID) {
1107 ODPH_ERR("Timeout event missing\n");
1108 return -1;
1109 }
1110
1111 gbl_args->event = ev;
1112
1113 /* Free schedule context */
1115 ODPH_ERR("Extra timeout event\n");
1116 return -1;
1117 }
1118 }
1119
1120 if (odp_event_type(gbl_args->event) != ODP_EVENT_TIMEOUT) {
1121 ODPH_ERR("Bad event type\n");
1122 return -1;
1123 }
1124
1125 gbl_args->timeout = odp_timeout_from_event(gbl_args->event);
1126
1127 return 0;
1128}
1129
1130static void init_suite(gbl_args_t *gbl_args)
1131{
1132 if (gbl_args->opt.mode == M_LATENCY) {
1133 bench_tm_suite_init(&gbl_args->suite.t);
1134 gbl_args->suite.t.bench = test_suite_tm;
1135 gbl_args->suite.t.num_bench = ODPH_ARRAY_SIZE(test_suite_tm);
1136 gbl_args->suite.t.rounds = REPEAT_COUNT;
1137 gbl_args->suite.t.bench_idx = gbl_args->opt.bench_idx;
1138 gbl_args->suite.t.measure_time = !!gbl_args->opt.time;
1139 gbl_args->suite.exit = &gbl_args->suite.t.exit_worker;
1140 gbl_args->suite.retval = &gbl_args->suite.t.retval;
1141 gbl_args->suite.args = &gbl_args->suite.t;
1142 gbl_args->suite.suite_fn = bench_tm_run;
1143 gbl_args->suite.export_fn = bench_timer_tm_export;
1144 gbl_args->suite.t.result = gbl_args->result.t;
1145 } else {
1146 bench_suite_init(&gbl_args->suite.b);
1147 gbl_args->suite.b.bench = test_suite;
1148 gbl_args->suite.b.num_bench = ODPH_ARRAY_SIZE(test_suite);
1149 gbl_args->suite.b.indef_idx = gbl_args->opt.bench_idx;
1150 gbl_args->suite.b.rounds = gbl_args->opt.rounds;
1151 gbl_args->suite.b.repeat_count = REPEAT_COUNT;
1152 gbl_args->suite.b.measure_time = !!gbl_args->opt.time;
1153 gbl_args->suite.exit = &gbl_args->suite.b.exit_worker;
1154 gbl_args->suite.retval = &gbl_args->suite.b.retval;
1155 gbl_args->suite.args = &gbl_args->suite.b;
1156 gbl_args->suite.suite_fn = bench_run;
1157 gbl_args->suite.export_fn = bench_timer_export;
1158 gbl_args->suite.b.result = gbl_args->result.b;
1159 }
1160}
1161
1162static void drain_timeouts(void)
1163{
1164 const int is_plain = gbl_args->plain_queue;
1165 odp_queue_t q = gbl_args->queue;
1166 odp_event_t ev;
1167 const uint64_t wait = odp_schedule_wait_time(2 * gbl_args->timer_nsec);
1168
1169 while (true) {
1170 ev = is_plain ? odp_queue_deq(q) : odp_schedule(NULL, wait);
1171
1172 if (ev == ODP_EVENT_INVALID)
1173 break;
1174
1175 /* The used tmo event will be freed in tester teardown. */
1176 }
1177}
1178
1179int main(int argc, char *argv[])
1180{
1181 odph_helper_options_t helper_options;
1182 test_common_options_t common_options;
1183 odph_thread_t worker_thread;
1184 odph_thread_common_param_t thr_common;
1185 odph_thread_param_t thr_param;
1186 int cpu, i;
1187 odp_shm_t shm;
1188 odp_cpumask_t cpumask, default_mask;
1189 odp_instance_t instance;
1190 odp_init_t init_param;
1191 int ret = 0;
1192
1193 /* Let helper collect its own arguments (e.g. --odph_proc) */
1194 argc = odph_parse_options(argc, argv);
1195 if (odph_options(&helper_options)) {
1196 ODPH_ERR("Reading ODP helper options failed\n");
1197 exit(EXIT_FAILURE);
1198 }
1199
1200 argc = test_common_parse_options(argc, argv);
1201 if (test_common_options(&common_options)) {
1202 ODPH_ERR("Reading test options failed\n");
1203 exit(EXIT_FAILURE);
1204 }
1205
1206 odp_init_param_init(&init_param);
1207 init_param.mem_model = helper_options.mem_model;
1208
1209 /* Init ODP before calling anything else */
1210 if (odp_init_global(&instance, &init_param, NULL)) {
1211 ODPH_ERR("Global init failed\n");
1212 exit(EXIT_FAILURE);
1213 }
1214
1215 /* Init this thread */
1216 if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
1217 ODPH_ERR("Local init failed\n");
1218 exit(EXIT_FAILURE);
1219 }
1220
1221 if (setup_sig_handler()) {
1222 ODPH_ERR("Signal handler setup failed\n");
1223 exit(EXIT_FAILURE);
1224 }
1225
1226 odp_schedule_config(NULL);
1227
1228 /* Reserve memory for args from shared mem */
1229 shm = odp_shm_reserve("shm_args", sizeof(gbl_args_t), ODP_CACHE_LINE_SIZE, 0);
1230 if (shm == ODP_SHM_INVALID) {
1231 ODPH_ERR("Shared mem reserve failed\n");
1232 exit(EXIT_FAILURE);
1233 }
1234
1235 gbl_args = odp_shm_addr(shm);
1236 if (gbl_args == NULL) {
1237 ODPH_ERR("Shared mem alloc failed\n");
1238 exit(EXIT_FAILURE);
1239 }
1240
1241 memset(gbl_args, 0, sizeof(gbl_args_t));
1242 gbl_args->timer_pool = ODP_TIMER_POOL_INVALID;
1243 gbl_args->timer = ODP_TIMER_INVALID;
1244 gbl_args->queue = ODP_QUEUE_INVALID;
1245 gbl_args->pool = ODP_POOL_INVALID;
1246 gbl_args->timeout = ODP_TIMEOUT_INVALID;
1247
1248 for (i = 0; i < REPEAT_COUNT; i++) {
1249 gbl_args->a1[i] = i;
1250 gbl_args->ev[i] = ODP_EVENT_INVALID;
1251 gbl_args->tmo[i] = ODP_TIMEOUT_INVALID;
1252 gbl_args->tim_src[i] = ODP_TIMER_INVALID;
1253 gbl_args->tim_dst[i] = ODP_TIMER_INVALID;
1254 }
1255
1256 /* Parse and store the application arguments */
1257 ret = parse_args(argc, argv);
1258 if (ret)
1259 goto exit;
1260
1261 init_suite(gbl_args);
1262
1263 /* Get default worker cpumask */
1264 if (odp_cpumask_default_worker(&default_mask, 1) != 1) {
1265 ODPH_ERR("Unable to allocate worker thread\n");
1266 ret = -1;
1267 goto exit;
1268 }
1269
1270 (void)odp_cpumask_to_str(&default_mask, gbl_args->cpumask_str,
1271 sizeof(gbl_args->cpumask_str));
1272
1273 /* Create timers and other resources */
1274 ret = create_timers();
1275 if (ret)
1276 goto exit;
1277
1278 print_info();
1279
1280 /* Start one timer and wait for the timeout event. Timer expiration fills in
1281 * timeout event metadata. */
1282 ret = wait_timer();
1283 if (ret)
1284 goto exit;
1285
1286 memset(&worker_thread, 0, sizeof(odph_thread_t));
1287
1288 /* Create worker thread */
1289 cpu = odp_cpumask_first(&default_mask);
1290
1291 odp_cpumask_zero(&cpumask);
1292 odp_cpumask_set(&cpumask, cpu);
1293
1294 odph_thread_common_param_init(&thr_common);
1295 thr_common.instance = instance;
1296 thr_common.cpumask = &cpumask;
1297 thr_common.share_param = 1;
1298
1299 odph_thread_param_init(&thr_param);
1300 thr_param.start = gbl_args->suite.suite_fn;
1301 thr_param.arg = gbl_args->suite.args;
1302 thr_param.thr_type = ODP_THREAD_WORKER;
1303
1304 odph_thread_create(&worker_thread, &thr_common, &thr_param, 1);
1305
1306 odph_thread_join(&worker_thread, 1);
1307 /* Drain those timeouts that were not successfully cancelled for some reason. */
1308 drain_timeouts();
1309
1310 if (gbl_args->suite.dummy)
1311 printf("(dummy result: 0x%" PRIx64 ")\n\n", gbl_args->suite.dummy);
1312
1313 ret = *gbl_args->suite.retval;
1314
1315 if (ret == 0 && common_options.is_export) {
1316 if (gbl_args->suite.export_fn(gbl_args)) {
1317 ODPH_ERR("Error: Export failed\n");
1318 ret = -1;
1319 }
1320 }
1321
1322exit:
1323 if (gbl_args->timeout != ODP_TIMEOUT_INVALID)
1324 odp_timeout_free(gbl_args->timeout);
1325
1326 if (gbl_args->pool != ODP_POOL_INVALID)
1327 odp_pool_destroy(gbl_args->pool);
1328
1329 if (gbl_args->timer != ODP_TIMER_INVALID) {
1330 if (odp_timer_free(gbl_args->timer)) {
1331 ODPH_ERR("Timer free failed\n");
1332 exit(EXIT_FAILURE);
1333 }
1334 }
1335
1336 for (i = 0; i < REPEAT_COUNT; i++) {
1337 if (gbl_args->tim_src[i] != ODP_TIMER_INVALID) {
1338 if (odp_timer_free(gbl_args->tim_src[i])) {
1339 ODPH_ERR("Timer free failed\n");
1340 exit(EXIT_FAILURE);
1341 }
1342 }
1343 }
1344
1345 if (gbl_args->timer_pool != ODP_TIMER_POOL_INVALID)
1346 odp_timer_pool_destroy(gbl_args->timer_pool);
1347
1348 if (gbl_args->queue != ODP_QUEUE_INVALID) {
1349 if (odp_queue_destroy(gbl_args->queue)) {
1350 ODPH_ERR("Queue destroy failed\n");
1351 exit(EXIT_FAILURE);
1352 }
1353 }
1354
1355 if (odp_shm_free(shm)) {
1356 ODPH_ERR("Shared mem free failed\n");
1357 exit(EXIT_FAILURE);
1358 }
1359
1360 if (odp_term_local()) {
1361 ODPH_ERR("Local term failed\n");
1362 exit(EXIT_FAILURE);
1363 }
1364
1365 if (odp_term_global(instance)) {
1366 ODPH_ERR("Global term failed\n");
1367 exit(EXIT_FAILURE);
1368 }
1369
1370 if (ret < 0)
1371 return EXIT_FAILURE;
1372
1373 return EXIT_SUCCESS;
1374}
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
#define ODP_UNUSED
Intentionally unused variables of functions.
Definition spec/hints.h:54
void odp_cpumask_set(odp_cpumask_t *mask, int cpu)
Add CPU to mask.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
void odp_cpumask_zero(odp_cpumask_t *mask)
Clear entire CPU mask.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
odp_event_type_t odp_event_type(odp_event_t event)
Event type of an event.
uint64_t odp_event_to_u64(odp_event_t hdl)
Get printable value for an odp_event_t.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
#define ODP_STATIC_ASSERT(cond, msg)
Compile time assertion macro.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
int odp_pool_capability(odp_pool_capability_t *capa)
Query pool capabilities.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_TIMEOUT
Timeout pool.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
@ ODP_QUEUE_TYPE_PLAIN
Plain queue.
#define ODP_SCHED_SYNC_ATOMIC
Atomic queue synchronization.
#define ODP_SCHED_NO_WAIT
Do not wait.
int odp_schedule_default_prio(void)
Default scheduling priority level.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
void odp_time_wait_ns(uint64_t ns)
Wait the specified number of nanoseconds.
uint64_t odp_time_global_strict_ns(void)
Current global time in nanoseconds (strict)
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
uint64_t odp_time_global_ns(void)
Current global time in nanoseconds.
void odp_timeout_free(odp_timeout_t tmo)
Timeout free.
uint64_t odp_timer_tick_to_ns(odp_timer_pool_t timer_pool, uint64_t ticks)
Convert timer ticks to nanoseconds.
int odp_timer_pool_start_multi(odp_timer_pool_t timer_pool[], int num)
Start timer pools.
void * odp_timeout_user_ptr(odp_timeout_t tmo)
Return user pointer for the timeout.
odp_timeout_t odp_timeout_alloc(odp_pool_t pool)
Timeout alloc.
uint64_t odp_timeout_tick(odp_timeout_t tmo)
Timeout expiration tick.
void * odp_timeout_user_area(odp_timeout_t tmo)
Timeout user area.
int odp_timer_free(odp_timer_t timer)
Free a timer.
odp_timeout_t odp_timeout_from_event(odp_event_t ev)
Get timeout handle from an ODP_EVENT_TIMEOUT type event.
#define ODP_TIMER_POOL_INVALID
Invalid timer pool handle.
odp_timer_pool_t odp_timer_pool_create(const char *name, const odp_timer_pool_param_t *params)
Create a timer pool.
odp_timer_t odp_timeout_timer(odp_timeout_t tmo)
Return timer handle for the timeout.
int odp_timer_cancel(odp_timer_t timer, odp_event_t *tmo_ev)
Cancel a single shot timer.
uint64_t odp_timer_current_tick(odp_timer_pool_t timer_pool)
Current tick value.
int odp_timer_capability(odp_timer_clk_src_t clk_src, odp_timer_capability_t *capa)
Query timer capabilities per clock source.
uint64_t odp_timer_ns_to_tick(odp_timer_pool_t timer_pool, uint64_t ns)
Convert nanoseconds to timer ticks.
uint64_t odp_timeout_to_u64(odp_timeout_t tmo)
Get printable value for an odp_timeout_t.
odp_timer_clk_src_t
Clock sources for timer pools.
int odp_timer_start(odp_timer_t timer, const odp_timer_start_t *start_param)
Start a single shot timer.
odp_event_t odp_timeout_to_event(odp_timeout_t tmo)
Convert timeout handle to event handle.
#define ODP_TIMEOUT_INVALID
Invalid timeout handle.
odp_timer_t odp_timer_alloc(odp_timer_pool_t timer_pool, odp_queue_t queue, const void *user_ptr)
Allocate a single shot timer.
#define ODP_CLOCK_DEFAULT
The default clock source.
uint64_t odp_timer_pool_to_u64(odp_timer_pool_t timer_pool)
Get printable value for an odp_timer_pool_t.
int odp_timeout_is_periodic(odp_timeout_t tmo)
Check if timeout is from a periodic timer.
#define ODP_TIMER_INVALID
Invalid timer handle.
uint64_t odp_timer_to_u64(odp_timer_t timer)
Get printable value for an odp_timer_t.
void odp_timer_pool_param_init(odp_timer_pool_param_t *param)
Initialize timer pool parameters.
void odp_timer_pool_destroy(odp_timer_pool_t timer_pool)
Destroy a timer pool.
@ ODP_TIMER_SUCCESS
Timer operation succeeded.
@ ODP_TIMER_FAIL
Timer operation failed.
@ ODP_TIMER_TICK_REL
Relative ticks.
The OpenDataPlane API.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
struct odp_pool_capability_t::@135 tmo
Timeout pool capabilities
uint32_t max_uarea_size
Maximum user area size in bytes.
uint32_t uarea_size
Minimum user area size in bytes.
uint32_t num
Number of buffers in the pool.
odp_pool_type_t type
Pool type.
struct odp_pool_param_t::@140 tmo
Parameters for timeout pools.
ODP Queue parameters.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
uint32_t max_timers
Maximum number of single shot timers in a pool.
odp_timer_res_capability_t max_res
Maximum resolution.
odp_bool_t queue_type_sched
Scheduled queue destination support.
Timer pool parameters.
uint64_t res_ns
Timeout resolution in nanoseconds.
uint64_t min_tmo
Minimum relative timeout in nanoseconds.
uint32_t num_timers
Number of timers in the pool.
odp_timer_clk_src_t clk_src
Clock source for timers.
uint64_t max_tmo
Maximum relative timeout in nanoseconds.
uint64_t max_tmo
Maximum relative timeout in nanoseconds.
uint64_t min_tmo
Minimum relative timeout in nanoseconds.
uint64_t res_ns
Timeout resolution in nanoseconds.
Timer start parameters.
uint64_t tick
Expiration time in ticks.
odp_event_t tmo_ev
Timeout event.
odp_timer_tick_type_t tick_type
Tick type.