API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_bench_queue.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2025-2026 Nokia
3 */
4
12#ifndef _GNU_SOURCE
13#define _GNU_SOURCE
14#endif
15
16#include <odp_api.h>
17#include <odp/helper/odph_api.h>
18
19#include <bench_common.h>
20#include <export_results.h>
21
22#include <getopt.h>
23#include <inttypes.h>
24#include <signal.h>
25#include <stdlib.h>
26#include <unistd.h>
27
28#define TEST_MAX_BURST 32U
29#define TEST_DEF_BURST 8U
30#define TEST_REPEAT_COUNT 1000U
31#define TEST_ROUNDS 100U
32#define TEST_MAX_QUEUES (32U * 1024U)
33#define TEST_MAX_BENCH 40U
34#define TEST_MAX_DATA_ARR (TEST_MAX_BURST * TEST_REPEAT_COUNT)
35
36#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
37 strrchr((file_name), '/') + 1 : (file_name))
38
39#define BENCH_INFO_1(run_fn, init_fn, term_fn) \
40 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .desc = NULL}
41
42#define BENCH_INFO_2(fn_name, run_fn, init_fn, term_fn) \
43 {.name = fn_name, .run = run_fn, .init = init_fn, .term = term_fn, .desc = NULL}
44
45#define BENCH_INFO_TM_1(run_fn, init_fn, term_fn) \
46 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .cond = NULL,\
47 .max_rounds = 0}
48
49#define BENCH_INFO_TM_2(fn_name, run_fn, init_fn, term_fn) \
50 {.name = fn_name, .run = run_fn, .init = init_fn, .term = term_fn, .cond = NULL,\
51 .max_rounds = 0}
52
53typedef enum {
54 M_TPUT,
55 M_LATENCY
56} meas_mode_t;
57
58typedef struct {
59 uint32_t burst_size;
60 uint32_t num_queues;
61 uint32_t bench_idx;
62 uint32_t rounds;
63 meas_mode_t mode;
64 odp_bool_t is_time;
65} appl_args_t;
66
67typedef struct {
68 appl_args_t appl;
69 char cpumask_str[ODP_CPUMASK_STR_SIZE];
70
71 struct {
72 uint32_t num_buf;
73 uint32_t buf_size;
74 odp_pool_t pool;
75 odp_queue_t p_q;
76 odp_queue_t s_q;
77 } resources;
78
79 struct {
80 odp_event_t evs[TEST_MAX_DATA_ARR];
81 void *ptrs[TEST_MAX_DATA_ARR];
82 } data;
83
84 struct {
85 union {
86 bench_suite_t b;
87 bench_tm_suite_t t;
88 } s;
89
90 odp_atomic_u32_t *exit;
91 int *retval;
92 void *args;
93 int (*suite_fn)(void *args);
94 int (*export_fn)(void *data);
95
96 union {
97 double b[TEST_MAX_BENCH];
98 bench_tm_result_t t[TEST_MAX_BENCH];
99 } r;
100 } suite;
101
102 uint8_t context[ODP_CACHE_LINE_SIZE];
103} args_t;
104
105static args_t *gbl_args;
106
107static void init_src_events(void)
108{
109 uint32_t i;
110 const uint32_t num = gbl_args->resources.num_buf;
111 odp_buffer_t buf;
112
113 for (i = 0U; i < num; i++) {
114 buf = odp_buffer_alloc(gbl_args->resources.pool);
115
116 if (buf == ODP_BUFFER_INVALID)
117 /* There should be enough buffers to allocate so abort in case of an
118 * error */
119 ODPH_ABORT("Failed to allocate\n");
120
121 gbl_args->data.evs[i] = odp_buffer_to_event(buf);
122 }
123
124 for (uint32_t j = i; j < ODPH_ARRAY_SIZE(gbl_args->data.evs); j++)
125 gbl_args->data.evs[j] = ODP_EVENT_INVALID;
126}
127
128static void term_partial_events(uint32_t start_idx)
129{
130 odp_event_t ev;
131
132 for (uint32_t i = start_idx; i < ODPH_ARRAY_SIZE(gbl_args->data.evs); i++) {
133 ev = gbl_args->data.evs[i];
134
135 if (ev != ODP_EVENT_INVALID)
136 odp_event_free(ev);
137 }
138}
139
140static void term_src_events(void)
141{
142 odp_event_t ev;
143 uint32_t i = 0U;
144
145 while (true) {
146 ev = odp_queue_deq(gbl_args->resources.p_q);
147
148 if (ev == ODP_EVENT_INVALID)
149 break;
150
151 odp_event_free(ev);
152 i++;
153 }
154
155 term_partial_events(i);
156}
157
158static void init_events(void)
159{
160 for (uint32_t i = 0U; i < ODPH_ARRAY_SIZE(gbl_args->data.evs); i++)
161 gbl_args->data.evs[i] = ODP_EVENT_INVALID;
162}
163
164static void fill_plain_queues(void)
165{
166 const uint32_t num = gbl_args->resources.num_buf;
167 odp_buffer_t buf;
168 odp_queue_t dst = gbl_args->resources.p_q;
169
170 for (uint32_t i = 0U; i < num; i++) {
171 buf = odp_buffer_alloc(gbl_args->resources.pool);
172
173 if (buf == ODP_BUFFER_INVALID)
174 /* There should be enough buffers to allocate so abort in case of an
175 * error */
176 ODPH_ABORT("Failed to allocate\n");
177
178 if (odp_queue_enq(dst, odp_buffer_to_event(buf)) < 0)
179 /* There should be enough room to enqueue test buffers to destination
180 * queues so abort in case of an error */
181 ODPH_ABORT("Failed to enqueue\n");
182 }
183
184 init_events();
185}
186
187static void term_events(void)
188{
189 odp_event_t ev;
190
191 for (uint32_t i = 0U; i < ODPH_ARRAY_SIZE(gbl_args->data.evs); i++) {
192 ev = gbl_args->data.evs[i];
193
194 if (ev != ODP_EVENT_INVALID)
195 odp_event_free(ev);
196 }
197}
198
199static void term_dst_events(void)
200{
201 odp_event_t ev;
202
203 while (true) {
204 ev = odp_queue_deq(gbl_args->resources.p_q);
205
206 if (ev == ODP_EVENT_INVALID)
207 break;
208
209 odp_event_free(ev);
210 }
211
212 term_events();
213}
214
215static void fill_scheduled_queues(void)
216{
217 const uint32_t num = gbl_args->resources.num_buf;
218 odp_buffer_t buf;
219 odp_queue_t dst = gbl_args->resources.s_q;
220
221 for (uint32_t i = 0U; i < num; i++) {
222 buf = odp_buffer_alloc(gbl_args->resources.pool);
223
224 if (buf == ODP_BUFFER_INVALID)
225 /* There should be enough buffers to allocate so abort in case of an
226 * error */
227 ODPH_ABORT("Failed to allocate\n");
228
229 if (odp_queue_enq(dst, odp_buffer_to_event(buf)) < 0)
230 /* There should be enough room to enqueue test buffers to destination
231 * queues so abort in case of an error */
232 ODPH_ABORT("Failed to enqueue\n");
233 }
234
235 init_events();
236}
237
238static void term_scheduled_src_events(void)
239{
240 odp_event_t ev;
241 uint32_t i = 0U;
242
243 while (true) {
245
246 if (ev == ODP_EVENT_INVALID)
247 break;
248
249 odp_event_free(ev);
250 i++;
251 }
252
253 term_partial_events(i);
254}
255
256static void term_scheduled_dst_events(void)
257{
258 odp_event_t ev;
259
260 while (true) {
262
263 if (ev == ODP_EVENT_INVALID)
264 break;
265
266 odp_event_free(ev);
267 }
268
269 term_events();
270}
271
272static int queue_context_set_plain(void)
273{
274 odp_queue_t dst = gbl_args->resources.p_q;
275 uint8_t *context = gbl_args->context;
276 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
277 int ret = 0;
278
279 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
280 ret += odp_queue_context_set(dst, context, len);
281
282 return !ret;
283}
284
285static int queue_context_set_plain_tm(bench_tm_result_t *res, int repeat_count)
286{
287 bench_tm_stamp_t s1, s2;
288 odp_queue_t dst = gbl_args->resources.p_q;
289 uint8_t *context = gbl_args->context;
290 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
291 int ret = 0;
292 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_context_set()");
293
294 for (int i = 0U; i < repeat_count; i++) {
295 bench_tm_now(res, &s1);
296 ret += odp_queue_context_set(dst, context, len);
297 bench_tm_now(res, &s2);
298 bench_tm_func_record(&s2, &s1, res, id1);
299 }
300
301 return !ret;
302}
303
304static int queue_context_plain(void)
305{
306 odp_queue_t q = gbl_args->resources.p_q;
307 void **dst = gbl_args->data.ptrs;
308
309 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
310 dst[i] = odp_queue_context(q);
311
312 return 1;
313}
314
315static int queue_context_plain_tm(bench_tm_result_t *res, int repeat_count)
316{
317 bench_tm_stamp_t s1, s2;
318 odp_queue_t q = gbl_args->resources.p_q;
319 void **dst = gbl_args->data.ptrs;
320 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_context()");
321
322 for (int i = 0U; i < repeat_count; i++) {
323 bench_tm_now(res, &s1);
324 dst[i] = odp_queue_context(q);
325 bench_tm_now(res, &s2);
326 bench_tm_func_record(&s2, &s1, res, id1);
327 }
328
329 return 1;
330}
331
332static int queue_context_set_scheduled(void)
333{
334 odp_queue_t dst = gbl_args->resources.s_q;
335 uint8_t *context = gbl_args->context;
336 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
337 int ret = 0;
338
339 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
340 ret += odp_queue_context_set(dst, context, len);
341
342 return !ret;
343}
344
345static int queue_context_set_scheduled_tm(bench_tm_result_t *res, int repeat_count)
346{
347 bench_tm_stamp_t s1, s2;
348 odp_queue_t dst = gbl_args->resources.s_q;
349 uint8_t *context = gbl_args->context;
350 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
351 int ret = 0;
352 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_context_set()");
353
354 for (int i = 0U; i < repeat_count; i++) {
355 bench_tm_now(res, &s1);
356 ret += odp_queue_context_set(dst, context, len);
357 bench_tm_now(res, &s2);
358 bench_tm_func_record(&s2, &s1, res, id1);
359 }
360
361 return !ret;
362}
363
364static int queue_context_scheduled(void)
365{
366 odp_queue_t q = gbl_args->resources.s_q;
367 void **dst = gbl_args->data.ptrs;
368
369 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
370 dst[i] = odp_queue_context(q);
371
372 return 1;
373}
374
375static int queue_context_scheduled_tm(bench_tm_result_t *res, int repeat_count)
376{
377 bench_tm_stamp_t s1, s2;
378 odp_queue_t q = gbl_args->resources.s_q;
379 void **dst = gbl_args->data.ptrs;
380 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_context()");
381
382 for (int i = 0U; i < repeat_count; i++) {
383 bench_tm_now(res, &s1);
384 dst[i] = odp_queue_context(q);
385 bench_tm_now(res, &s2);
386 bench_tm_func_record(&s2, &s1, res, id1);
387 }
388
389 return 1;
390}
391
392static int queue_enq_plain(void)
393{
394 odp_queue_t dst = gbl_args->resources.p_q;
395 odp_event_t *src = gbl_args->data.evs;
396 int ret = 0;
397
398 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
399 ret += odp_queue_enq(dst, src[i]);
400
401 return !ret;
402}
403
404static int queue_enq_plain_tm(bench_tm_result_t *res, int repeat_count)
405{
406 bench_tm_stamp_t s1, s2;
407 odp_queue_t dst = gbl_args->resources.p_q;
408 odp_event_t *src = gbl_args->data.evs;
409 int ret = 0;
410 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_enq()");
411
412 for (int i = 0; i < repeat_count; i++) {
413 bench_tm_now(res, &s1);
414 ret += odp_queue_enq(dst, src[i]);
415 bench_tm_now(res, &s2);
416 bench_tm_func_record(&s2, &s1, res, id1);
417 }
418
419 return !ret;
420}
421
422static int queue_enq_multi_plain(void)
423{
424 odp_queue_t dst = gbl_args->resources.p_q;
425 odp_event_t *src = gbl_args->data.evs;
426 int num_tot = 0, ret;
427 const int num_burst = gbl_args->appl.burst_size;
428
429 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++) {
430 ret = odp_queue_enq_multi(dst, &src[num_tot], num_burst);
431
432 ODPH_ASSERT(ret >= 0);
433
434 num_tot += ret;
435 }
436
437 return 1;
438}
439
440static int queue_enq_multi_plain_tm(bench_tm_result_t *res, int repeat_count)
441{
442 bench_tm_stamp_t s1, s2;
443 odp_queue_t dst = gbl_args->resources.p_q;
444 odp_event_t *src = gbl_args->data.evs;
445 int num_tot = 0, ret;
446 const int num_burst = gbl_args->appl.burst_size;
447 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_enq_multi()");
448
449 for (int i = 0; i < repeat_count; i++) {
450 bench_tm_now(res, &s1);
451 ret = odp_queue_enq_multi(dst, &src[num_tot], num_burst);
452 bench_tm_now(res, &s2);
453
454 ODPH_ASSERT(ret >= 0);
455
456 bench_tm_func_record(&s2, &s1, res, id1);
457 num_tot += ret;
458 }
459
460 return 1;
461}
462
463static int queue_deq_plain(void)
464{
465 odp_queue_t src = gbl_args->resources.p_q;
466 odp_event_t *dst = gbl_args->data.evs;
467
468 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
469 dst[i] = odp_queue_deq(src);
470
471 return 1;
472}
473
474static int queue_deq_plain_tm(bench_tm_result_t *res, int repeat_count)
475{
476 bench_tm_stamp_t s1, s2;
477 odp_queue_t src = gbl_args->resources.p_q;
478 odp_event_t *dst = gbl_args->data.evs;
479 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_deq()");
480
481 for (int i = 0U; i < repeat_count; i++) {
482 bench_tm_now(res, &s1);
483 dst[i] = odp_queue_deq(src);
484 bench_tm_now(res, &s2);
485 bench_tm_func_record(&s2, &s1, res, id1);
486 }
487
488 return 1;
489}
490
491static int queue_deq_multi_plain(void)
492{
493 odp_queue_t src = gbl_args->resources.p_q;
494 odp_event_t *dst = gbl_args->data.evs;
495 int num_tot = 0, ret;
496 const int num_burst = gbl_args->appl.burst_size;
497
498 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++) {
499 ret = odp_queue_deq_multi(src, &dst[num_tot], num_burst);
500
501 ODPH_ASSERT(ret >= 0);
502
503 num_tot += ret;
504 }
505
506 return 1;
507}
508
509static int queue_deq_multi_plain_tm(bench_tm_result_t *res, int repeat_count)
510{
511 bench_tm_stamp_t s1, s2;
512 odp_queue_t src = gbl_args->resources.p_q;
513 odp_event_t *dst = gbl_args->data.evs;
514 int num_tot = 0, ret;
515 const int num_burst = gbl_args->appl.burst_size;
516 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_deq_multi()");
517
518 for (int i = 0U; i < repeat_count; i++) {
519 bench_tm_now(res, &s1);
520 ret = odp_queue_deq_multi(src, &dst[num_tot], num_burst);
521 bench_tm_now(res, &s2);
522
523 ODPH_ASSERT(ret >= 0);
524
525 bench_tm_func_record(&s2, &s1, res, id1);
526 num_tot += ret;
527 }
528
529 return 1;
530}
531
532static int queue_enq_scheduled(void)
533{
534 odp_queue_t dst = gbl_args->resources.s_q;
535 odp_event_t *src = gbl_args->data.evs;
536 int ret = 0;
537
538 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
539 ret += odp_queue_enq(dst, src[i]);
540
541 return !ret;
542}
543
544static int queue_enq_scheduled_tm(bench_tm_result_t *res, int repeat_count)
545{
546 bench_tm_stamp_t s1, s2;
547 odp_queue_t dst = gbl_args->resources.s_q;
548 odp_event_t *src = gbl_args->data.evs;
549 int ret = 0;
550 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_enq()");
551
552 for (int i = 0; i < repeat_count; i++) {
553 bench_tm_now(res, &s1);
554 ret += odp_queue_enq(dst, src[i]);
555 bench_tm_now(res, &s2);
556 bench_tm_func_record(&s2, &s1, res, id1);
557 }
558
559 return !ret;
560}
561
562static int queue_enq_multi_scheduled(void)
563{
564 odp_queue_t dst = gbl_args->resources.s_q;
565 odp_event_t *src = gbl_args->data.evs;
566 int num_tot = 0, ret;
567 const int num_burst = gbl_args->appl.burst_size;
568
569 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++) {
570 ret = odp_queue_enq_multi(dst, &src[num_tot], num_burst);
571
572 ODPH_ASSERT(ret >= 0);
573
574 num_tot += ret;
575 }
576
577 return 1;
578}
579
580static int queue_enq_multi_scheduled_tm(bench_tm_result_t *res, int repeat_count)
581{
582 bench_tm_stamp_t s1, s2;
583 odp_queue_t dst = gbl_args->resources.s_q;
584 odp_event_t *src = gbl_args->data.evs;
585 int num_tot = 0, ret;
586 const int num_burst = gbl_args->appl.burst_size;
587 const uint8_t id1 = bench_tm_func_register(res, "odp_queue_enq_multi()");
588
589 for (int i = 0; i < repeat_count; i++) {
590 bench_tm_now(res, &s1);
591 ret = odp_queue_enq_multi(dst, &src[num_tot], num_burst);
592 bench_tm_now(res, &s2);
593
594 ODPH_ASSERT(ret >= 0);
595
596 bench_tm_func_record(&s2, &s1, res, id1);
597 num_tot += ret;
598 }
599
600 return 1;
601}
602
603static int schedule(void)
604{
605 odp_event_t *dst = gbl_args->data.evs;
606
607 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
608 dst[i] = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
609
610 return 1;
611}
612
613static int schedule_tm(bench_tm_result_t *res, int repeat_count)
614{
615 bench_tm_stamp_t s1, s2;
616 odp_event_t *dst = gbl_args->data.evs;
617 const uint8_t id1 = bench_tm_func_register(res, "odp_schedule()");
618
619 for (int i = 0; i < repeat_count; i++) {
620 bench_tm_now(res, &s1);
621 dst[i] = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
622 bench_tm_now(res, &s2);
623 bench_tm_func_record(&s2, &s1, res, id1);
624 }
625
626 return 1;
627}
628
629static int schedule_prefetch_single(void)
630{
631 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
633
634 return 1;
635}
636
637static int schedule_prefetch_single_tm(bench_tm_result_t *res, int repeat_count)
638{
639 bench_tm_stamp_t s1, s2;
640 const uint8_t id1 = bench_tm_func_register(res, "odp_schedule_prefetch(1)");
641
642 for (int i = 0; i < repeat_count; i++) {
643 bench_tm_now(res, &s1);
645 bench_tm_now(res, &s2);
646 bench_tm_func_record(&s2, &s1, res, id1);
647 }
648
649 return 1;
650}
651
652static int schedule_multi_no_wait(void)
653{
654 odp_event_t *dst = gbl_args->data.evs;
655 const int num_burst = gbl_args->appl.burst_size;
656 int num_recv = 0;
657
658 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
659 num_recv += odp_schedule_multi_no_wait(NULL, &dst[num_recv], num_burst);
660
661 return 1;
662}
663
664static int schedule_multi_wait(void)
665{
666 odp_event_t *dst = gbl_args->data.evs;
667 const int num_burst = gbl_args->appl.burst_size;
668 int num_recv = 0;
669
670 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
671 num_recv += odp_schedule_multi_wait(NULL, &dst[num_recv], num_burst);
672
673 return 1;
674}
675
676static int schedule_multi_no_wait_tm(bench_tm_result_t *res, int repeat_count)
677{
678 bench_tm_stamp_t s1, s2;
679 odp_event_t *dst = gbl_args->data.evs;
680 const int num_burst = gbl_args->appl.burst_size;
681 int num_recv = 0;
682 const uint8_t id1 = bench_tm_func_register(res, "odp_schedule_multi_no_wait()");
683
684 for (int i = 0; i < repeat_count; i++) {
685 bench_tm_now(res, &s1);
686 num_recv += odp_schedule_multi_no_wait(NULL, &dst[num_recv], num_burst);
687 bench_tm_now(res, &s2);
688 bench_tm_func_record(&s2, &s1, res, id1);
689 }
690
691 return 1;
692}
693
694static int schedule_multi_wait_tm(bench_tm_result_t *res, int repeat_count)
695{
696 bench_tm_stamp_t s1, s2;
697 odp_event_t *dst = gbl_args->data.evs;
698 const int num_burst = gbl_args->appl.burst_size;
699 int num_recv = 0;
700 const uint8_t id1 = bench_tm_func_register(res, "odp_schedule_multi_wait()");
701
702 for (int i = 0; i < repeat_count; i++) {
703 bench_tm_now(res, &s1);
704 num_recv += odp_schedule_multi_wait(NULL, &dst[num_recv], num_burst);
705 bench_tm_now(res, &s2);
706 bench_tm_func_record(&s2, &s1, res, id1);
707 }
708
709 return 1;
710}
711
712static int schedule_multi(void)
713{
714 odp_event_t *dst = gbl_args->data.evs;
715 const int num_burst = gbl_args->appl.burst_size;
716 int num_recv = 0;
717
718 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
719 num_recv += odp_schedule_multi(NULL, ODP_SCHED_NO_WAIT, &dst[num_recv], num_burst);
720
721 return 1;
722}
723
724static int schedule_multi_tm(bench_tm_result_t *res, int repeat_count)
725{
726 bench_tm_stamp_t s1, s2;
727 odp_event_t *dst = gbl_args->data.evs;
728 const int num_burst = gbl_args->appl.burst_size;
729 int num_recv = 0;
730 const uint8_t id1 = bench_tm_func_register(res, "odp_schedule_multi()");
731
732 for (int i = 0; i < repeat_count; i++) {
733 bench_tm_now(res, &s1);
734 num_recv += odp_schedule_multi(NULL, ODP_SCHED_NO_WAIT, &dst[num_recv], num_burst);
735 bench_tm_now(res, &s2);
736 bench_tm_func_record(&s2, &s1, res, id1);
737 }
738
739 return 1;
740}
741
742static int schedule_prefetch_burst(void)
743{
744 const int num_burst = gbl_args->appl.burst_size;
745
746 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
747 odp_schedule_prefetch(num_burst);
748
749 return 1;
750}
751
752static int schedule_prefetch_burst_tm(bench_tm_result_t *res, int repeat_count)
753{
754 bench_tm_stamp_t s1, s2;
755 const int num_burst = gbl_args->appl.burst_size;
756 const uint8_t id1 = bench_tm_func_register(res, "odp_schedule_prefetch(burst)");
757
758 for (int i = 0; i < repeat_count; i++) {
759 bench_tm_now(res, &s1);
760 odp_schedule_prefetch(num_burst);
761 bench_tm_now(res, &s2);
762 bench_tm_func_record(&s2, &s1, res, id1);
763 }
764
765 return 1;
766}
767
768bench_info_t test_suite[] = {
769 BENCH_INFO_1(queue_context_set_plain, NULL, NULL),
770 BENCH_INFO_1(queue_context_plain, NULL, NULL),
771 BENCH_INFO_1(queue_context_set_scheduled, NULL, NULL),
772 BENCH_INFO_1(queue_context_scheduled, NULL, NULL),
773 BENCH_INFO_1(queue_enq_plain, init_src_events, term_src_events),
774 BENCH_INFO_1(queue_enq_multi_plain, init_src_events, term_src_events),
775 BENCH_INFO_1(queue_deq_plain, fill_plain_queues, term_dst_events),
776 BENCH_INFO_1(queue_deq_multi_plain, fill_plain_queues, term_dst_events),
777 BENCH_INFO_1(queue_enq_scheduled, init_src_events, term_scheduled_src_events),
778 BENCH_INFO_1(queue_enq_multi_scheduled, init_src_events, term_scheduled_src_events),
779 BENCH_INFO_2("schedule_empty", schedule, init_events, term_events),
780 BENCH_INFO_2("schedule_multi_no_wait_empty", schedule_multi_no_wait, init_events,
781 term_events),
782 BENCH_INFO_2("schedule_multi_empty", schedule_multi, init_events, term_events),
783 BENCH_INFO_2("schedule_full", schedule, fill_scheduled_queues, term_scheduled_dst_events),
784 BENCH_INFO_2("schedule_multi_no_wait_full", schedule_multi_no_wait, fill_scheduled_queues,
785 term_scheduled_dst_events),
786 BENCH_INFO_2("schedule_multi_wait_full", schedule_multi_wait, fill_scheduled_queues,
787 term_scheduled_dst_events),
788 BENCH_INFO_2("schedule_multi_full", schedule_multi, fill_scheduled_queues,
789 term_scheduled_dst_events),
790 BENCH_INFO_2("schedule_prefetch_single", schedule_prefetch_single, fill_scheduled_queues,
791 term_scheduled_dst_events),
792 BENCH_INFO_2("schedule_prefetch_burst", schedule_prefetch_burst, fill_scheduled_queues,
793 term_scheduled_dst_events),
794};
795
796ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite) < TEST_MAX_BENCH,
797 "Result array is too small to hold all the results");
798
799bench_tm_info_t test_suite_tm[] = {
800 BENCH_INFO_TM_1(queue_context_set_plain_tm, NULL, NULL),
801 BENCH_INFO_TM_1(queue_context_plain_tm, NULL, NULL),
802 BENCH_INFO_TM_1(queue_context_set_scheduled_tm, NULL, NULL),
803 BENCH_INFO_TM_1(queue_context_scheduled_tm, NULL, NULL),
804 BENCH_INFO_TM_1(queue_enq_plain_tm, init_src_events, term_src_events),
805 BENCH_INFO_TM_1(queue_enq_multi_plain_tm, init_src_events, term_src_events),
806 BENCH_INFO_TM_1(queue_deq_plain_tm, fill_plain_queues, term_dst_events),
807 BENCH_INFO_TM_1(queue_deq_multi_plain_tm, fill_plain_queues, term_dst_events),
808 BENCH_INFO_TM_1(queue_enq_scheduled_tm, init_src_events, term_scheduled_src_events),
809 BENCH_INFO_TM_1(queue_enq_multi_scheduled_tm, init_src_events, term_scheduled_src_events),
810 BENCH_INFO_TM_2("schedule_empty_tm", schedule_tm, init_events, term_events),
811 BENCH_INFO_TM_2("schedule_multi_no_wait_empty_tm", schedule_multi_no_wait_tm, init_events,
812 term_events),
813 BENCH_INFO_TM_2("schedule_multi_empty_tm", schedule_multi_tm, init_events, term_events),
814 BENCH_INFO_TM_2("schedule_full_tm", schedule_tm, fill_scheduled_queues,
815 term_scheduled_dst_events),
816 BENCH_INFO_TM_2("schedule_multi_no_wait_full_tm", schedule_multi_no_wait_tm,
817 fill_scheduled_queues, term_scheduled_dst_events),
818 BENCH_INFO_TM_2("schedule_multi_wait_full_tm", schedule_multi_wait_tm,
819 fill_scheduled_queues, term_scheduled_dst_events),
820 BENCH_INFO_TM_2("schedule_multi_full_tm", schedule_multi_tm, fill_scheduled_queues,
821 term_scheduled_dst_events),
822 BENCH_INFO_TM_2("schedule_prefetch_single_tm", schedule_prefetch_single_tm,
823 fill_scheduled_queues, term_scheduled_dst_events),
824 BENCH_INFO_TM_2("schedule_prefetch_burst_tm", schedule_prefetch_burst_tm,
825 fill_scheduled_queues, term_scheduled_dst_events),
826};
827
828ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite_tm) < TEST_MAX_BENCH,
829 "Result array is too small to hold all the results");
830
831static void set_defaults(void)
832{
833 gbl_args->appl.burst_size = TEST_DEF_BURST;
834 gbl_args->appl.num_queues = 1U; /* TODO: make CLI configurable */
835 gbl_args->appl.bench_idx = 0U; /* Run all benchmarks */
836 gbl_args->appl.rounds = TEST_ROUNDS;
837 gbl_args->appl.mode = M_TPUT;
838 gbl_args->appl.is_time = false;
839 gbl_args->resources.num_buf = TEST_DEF_BURST * TEST_REPEAT_COUNT;
840 gbl_args->resources.buf_size = ODP_CACHE_LINE_SIZE;
841 gbl_args->resources.pool = ODP_POOL_INVALID;
842 gbl_args->resources.p_q = ODP_QUEUE_INVALID;
843 gbl_args->resources.s_q = ODP_QUEUE_INVALID;
844}
845
846static void print_usage(char *progname)
847{
848 printf("\n"
849 "OpenDataPlane queue API microbenchmarks.\n"
850 "\n"
851 "Usage: %s OPTIONS\n"
852 " E.g. %s\n"
853 "\n"
854 "Optional OPTIONS:\n"
855 " -b, --burst <num> Test burst size for '*_multi()' functions. Maximum %u.\n"
856 " %u by default. Implementation capabilities may further\n"
857 " limit the value.\n"
858 " -i, --index <idx> Benchmark index to run indefinitely. Index should be\n"
859 " one-based. Use 0 to run all benchmarks. 0 by default.\n"
860 " Registered benchmarks:\n",
861 NO_PATH(progname), NO_PATH(progname), TEST_MAX_BURST, TEST_DEF_BURST);
862
863 /* Dump the to-be-tested functions for user-friendliness */
864 for (uint32_t i = 0U; i < ODPH_ARRAY_SIZE(test_suite); ++i)
865 printf(" %u: %s\n", i + 1U, test_suite[i].name);
866
867 printf(" -r, --rounds <num> Run each test case 'num' times. %u by default.\n"
868 " -t, --time <opt> Time measurement.\n"
869 " 0: measure CPU cycles (default)\n"
870 " 1: measure time\n"
871 " -m, --mode <mode> Measurement mode.\n"
872 " 0: measure throughput, track average execution\n"
873 " time (default)\n"
874 " 1: measure latency, track function minimum and\n"
875 " maximum in addition to average execution time.\n"
876 " -h, --help Display help and exit.\n\n"
877 "\n", TEST_ROUNDS);
878}
879
880static void check_args(void)
881{
885
886 gbl_args->resources.num_buf = TEST_REPEAT_COUNT * gbl_args->appl.burst_size;
887
888 if (gbl_args->appl.mode != M_TPUT && gbl_args->appl.mode != M_LATENCY) {
889 printf("Invalid measurement mode: %d\n", gbl_args->appl.mode);
890 exit(EXIT_FAILURE);
891 }
892
893 if (odp_pool_capability(&p_capa) < 0) {
894 ODPH_ERR("Failed to query pool capabilities\n");
895 exit(EXIT_FAILURE);
896 }
897
898 if (gbl_args->resources.num_buf > p_capa.buf.max_num) {
899 ODPH_ERR("Invalid amount of buffers: %u (max: %u)\n",
900 gbl_args->resources.num_buf, p_capa.buf.max_num);
901 exit(EXIT_FAILURE);
902 }
903
904 if (gbl_args->resources.buf_size > p_capa.buf.max_size)
905 gbl_args->resources.buf_size = p_capa.buf.max_size;
906
907 if (odp_queue_capability(&q_capa) < 0) {
908 ODPH_ERR("Failed to query queue capabilities\n");
909 exit(EXIT_FAILURE);
910 }
911
912 if (gbl_args->appl.num_queues * 2U > q_capa.max_queues) {
913 ODPH_ERR("Invalid number of queues: %u (max: %u, any type)\n",
914 gbl_args->appl.num_queues, q_capa.max_queues);
915 exit(EXIT_FAILURE);
916 }
917
918 if (gbl_args->appl.num_queues > q_capa.plain.max_num) {
919 ODPH_ERR("Invalid number of queues: %u (max: %u, plain)\n",
920 gbl_args->appl.num_queues, q_capa.max_queues);
921 exit(EXIT_FAILURE);
922 }
923
924 if (gbl_args->resources.num_buf > q_capa.plain.max_size) {
925 ODPH_ERR("Invalid queue size: %u (max: %u, plain)\n", gbl_args->resources.num_buf,
926 q_capa.plain.max_size);
927 exit(EXIT_FAILURE);
928 }
929
930 if (odp_schedule_capability(&s_capa) < 0) {
931 ODPH_ERR("Failed to query schedule capabilities\n");
932 exit(EXIT_FAILURE);
933 }
934
935 if (gbl_args->appl.num_queues > s_capa.max_queues) {
936 ODPH_ERR("Invalid number of queues: %u (max: %u, scheduled)\n",
937 gbl_args->appl.num_queues, s_capa.max_queues);
938 exit(EXIT_FAILURE);
939 }
940
941 if (gbl_args->resources.num_buf > s_capa.max_queue_size) {
942 ODPH_ERR("Invalid queue size: %u (max: %u, scheduled)\n",
943 gbl_args->resources.num_buf, s_capa.max_queue_size);
944 exit(EXIT_FAILURE);
945 }
946}
947
948static void parse_args(int argc, char *argv[])
949{
950 int opt;
951 static const struct option longopts[] = {
952 {"burst", required_argument, NULL, 'b'},
953 {"index", required_argument, NULL, 'i'},
954 {"rounds", required_argument, NULL, 'r'},
955 {"time", required_argument, NULL, 't'},
956 {"mode", required_argument, NULL, 'm'},
957 {"help", no_argument, NULL, 'h'},
958 {NULL, 0, NULL, 0}
959 };
960 static const char *shortopts = "b:i:r:t:m:h";
961 appl_args_t *appl_args = &gbl_args->appl;
962
963 while (true) {
964 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
965
966 if (opt == -1)
967 break;
968
969 switch (opt) {
970 case 'b':
971 appl_args->burst_size = atoi(optarg);
972 break;
973 case 'i':
974 appl_args->bench_idx = atoi(optarg);
975 break;
976 case 'r':
977 appl_args->rounds = atoi(optarg);
978 break;
979 case 't':
980 appl_args->is_time = atoi(optarg);
981 break;
982 case 'm':
983 appl_args->mode = atoi(optarg);
984 break;
985 case 'h':
986 print_usage(argv[0]);
987 exit(EXIT_SUCCESS);
988 break;
989 default:
990 break;
991 }
992 }
993
994 check_args();
995}
996
997static void sig_handler(int signo ODP_UNUSED)
998{
999 odp_atomic_store_u32(gbl_args->suite.exit, 1);
1000}
1001
1002static int setup_sig_handler(void)
1003{
1004 struct sigaction action;
1005
1006 memset(&action, 0, sizeof(action));
1007 action.sa_handler = sig_handler;
1008
1009 /* No additional signals blocked. By default, the signal which triggered
1010 * the handler is blocked. */
1011 if (sigemptyset(&action.sa_mask))
1012 return -1;
1013
1014 if (sigaction(SIGINT, &action, NULL))
1015 return -1;
1016
1017 return 0;
1018}
1019
1020static int bench_buffer_tm_export(void *data)
1021{
1022 args_t *gbl_args = data;
1023 bench_tm_result_t *res;
1024 uint64_t num;
1025 int ret = 0;
1026 const char *unit = gbl_args->appl.is_time ? "nsec" : "cpu cycles";
1027
1028 if (test_common_write("function name,min %s per function call,"
1029 "average %s per function call,"
1030 "max %s per function call\n", unit, unit, unit)) {
1031 ret = -1;
1032 goto exit;
1033 }
1034
1035 for (uint32_t i = 0; i < gbl_args->suite.s.t.num_bench; i++) {
1036 res = &gbl_args->suite.s.t.result[i];
1037
1038 for (int j = 0; j < res->num; j++) {
1039 num = res->func[j].num ? res->func[j].num : 1;
1040 if (test_common_write("%s,%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
1041 res->func[j].name,
1042 bench_tm_to_u64(res, &res->func[j].min),
1043 bench_tm_to_u64(res, &res->func[j].tot) / num,
1044 bench_tm_to_u64(res, &res->func[j].max))) {
1045 ret = -1;
1046 goto exit;
1047 }
1048 }
1049 }
1050
1051exit:
1052 test_common_write_term();
1053
1054 return ret;
1055}
1056
1057static int bench_buffer_export(void *data)
1058{
1059 args_t *gbl_args = data;
1060 int ret = 0;
1061
1062 if (test_common_write("%s", gbl_args->appl.is_time ?
1063 "function name,average nsec per function call\n" :
1064 "function name,average cpu cycles per function call\n")) {
1065 ret = -1;
1066 goto exit;
1067 }
1068
1069 for (int i = 0; i < gbl_args->suite.s.b.num_bench; i++) {
1070 if (test_common_write("odp_%s,%f\n", gbl_args->suite.s.b.bench[i].desc != NULL ?
1071 gbl_args->suite.s.b.bench[i].desc :
1072 gbl_args->suite.s.b.bench[i].name,
1073 gbl_args->suite.s.b.result[i])) {
1074 ret = -1;
1075 goto exit;
1076 }
1077 }
1078
1079exit:
1080 test_common_write_term();
1081
1082 return ret;
1083}
1084
1085static void init_suite(args_t *gbl_args)
1086{
1087 if (gbl_args->appl.mode == M_LATENCY) {
1088 bench_tm_suite_init(&gbl_args->suite.s.t);
1089 gbl_args->suite.s.t.bench = test_suite_tm;
1090 gbl_args->suite.s.t.num_bench = ODPH_ARRAY_SIZE(test_suite_tm);
1091 gbl_args->suite.s.t.rounds = TEST_REPEAT_COUNT;
1092 gbl_args->suite.s.t.bench_idx = gbl_args->appl.bench_idx;
1093 gbl_args->suite.s.t.measure_time = gbl_args->appl.is_time;
1094 gbl_args->suite.exit = &gbl_args->suite.s.t.exit_worker;
1095 gbl_args->suite.retval = &gbl_args->suite.s.t.retval;
1096 gbl_args->suite.args = &gbl_args->suite.s.t;
1097 gbl_args->suite.suite_fn = bench_tm_run;
1098 gbl_args->suite.export_fn = bench_buffer_tm_export;
1099 gbl_args->suite.s.t.result = gbl_args->suite.r.t;
1100 } else {
1101 bench_suite_init(&gbl_args->suite.s.b);
1102 gbl_args->suite.s.b.bench = test_suite;
1103 gbl_args->suite.s.b.num_bench = ODPH_ARRAY_SIZE(test_suite);
1104 gbl_args->suite.s.b.indef_idx = gbl_args->appl.bench_idx;
1105 gbl_args->suite.s.b.rounds = gbl_args->appl.rounds;
1106 gbl_args->suite.s.b.repeat_count = TEST_REPEAT_COUNT;
1107 gbl_args->suite.s.b.measure_time = gbl_args->appl.is_time;
1108 gbl_args->suite.exit = &gbl_args->suite.s.b.exit_worker;
1109 gbl_args->suite.retval = &gbl_args->suite.s.b.retval;
1110 gbl_args->suite.args = &gbl_args->suite.s.b;
1111 gbl_args->suite.suite_fn = bench_run;
1112 gbl_args->suite.export_fn = bench_buffer_export;
1113 gbl_args->suite.s.b.result = gbl_args->suite.r.b;
1114 }
1115}
1116
1117static int create_resources(void)
1118{
1119 odp_pool_param_t p_param;
1120 odp_queue_param_t q_param;
1121
1122 if (odp_schedule_config(NULL)) {
1123 ODPH_ERR("Failed to configure scheduler\n");
1124 return -1;
1125 }
1126
1127 odp_pool_param_init(&p_param);
1128 p_param.type = ODP_POOL_BUFFER;
1129 p_param.buf.num = gbl_args->resources.num_buf;
1130 p_param.buf.size = gbl_args->resources.buf_size;
1131 gbl_args->resources.pool = odp_pool_create("bq_pool", &p_param);
1132
1133 if (gbl_args->resources.pool == ODP_POOL_INVALID) {
1134 ODPH_ERR("Failed to create test pool\n");
1135 return -1;
1136 }
1137
1138 odp_queue_param_init(&q_param);
1141 q_param.context = gbl_args->context;
1142 q_param.size = gbl_args->resources.num_buf;
1143 gbl_args->resources.p_q = odp_queue_create("bq_plain", &q_param);
1144
1145 if (gbl_args->resources.p_q == ODP_QUEUE_INVALID) {
1146 ODPH_ERR("Failed to create plain test queue\n");
1147 return -1;
1148 }
1149
1150 q_param.type = ODP_QUEUE_TYPE_SCHED;
1151 gbl_args->resources.s_q = odp_queue_create("bq_sched", &q_param);
1152
1153 if (gbl_args->resources.s_q == ODP_QUEUE_INVALID) {
1154 ODPH_ERR("Failed to create scheduled test queue\n");
1155 return -1;
1156 }
1157
1158 return 0;
1159}
1160
1161static void print_info(void)
1162{
1164 printf("\n"
1165 "odp_queue_buffer options\n"
1166 "------------------------\n");
1167
1168 printf("Burst size: %d\n", gbl_args->appl.burst_size);
1169 printf("CPU mask: %s\n", gbl_args->cpumask_str);
1170 printf("Measurement unit: %s\n", gbl_args->appl.is_time ? "nsec" : "CPU cycles");
1171 printf("Test rounds: %u\n", gbl_args->appl.rounds);
1172 printf("Measurement mode: %s\n", gbl_args->appl.mode == M_TPUT ? "throughput" : "latency");
1173 printf("\n");
1174}
1175
1176static void run_worker(odp_instance_t instance, odp_cpumask_t default_mask)
1177{
1178 const int cpu = odp_cpumask_first(&default_mask);
1179 odp_cpumask_t cpumask;
1180 odph_thread_t worker_thread;
1181 odph_thread_common_param_t thr_common;
1182 odph_thread_param_t thr_param;
1183
1184 memset(&worker_thread, 0, sizeof(odph_thread_t));
1185 odp_cpumask_zero(&cpumask);
1186 odp_cpumask_set(&cpumask, cpu);
1187 odph_thread_common_param_init(&thr_common);
1188 thr_common.instance = instance;
1189 thr_common.cpumask = &cpumask;
1190 thr_common.share_param = 1;
1191 odph_thread_param_init(&thr_param);
1192 thr_param.start = gbl_args->suite.suite_fn;
1193 thr_param.arg = gbl_args->suite.args;
1194 thr_param.thr_type = ODP_THREAD_WORKER;
1195
1196 if (odph_thread_create(&worker_thread, &thr_common, &thr_param, 1) != 1) {
1197 ODPH_ERR("Creating worker thread failed\n");
1198 exit(EXIT_FAILURE);
1199 }
1200
1201 (void)odph_thread_join(&worker_thread, 1);
1202}
1203
1204static void teardown_resources(void)
1205{
1206 (void)odp_queue_destroy(gbl_args->resources.s_q);
1207 (void)odp_queue_destroy(gbl_args->resources.p_q);
1208 (void)odp_pool_destroy(gbl_args->resources.pool);
1209}
1210
1211int main(int argc, char *argv[])
1212{
1213 odph_helper_options_t helper_options;
1214 test_common_options_t common_options;
1215 odp_shm_t shm;
1216 odp_cpumask_t default_mask;
1217 odp_instance_t instance;
1218 odp_init_t init_param;
1219 uint8_t ret;
1220
1221 argc = odph_parse_options(argc, argv);
1222
1223 if (odph_options(&helper_options)) {
1224 ODPH_ERR("Reading ODP helper options failed\n");
1225 exit(EXIT_FAILURE);
1226 }
1227
1228 argc = test_common_parse_options(argc, argv);
1229
1230 if (test_common_options(&common_options)) {
1231 ODPH_ERR("Reading test options failed\n");
1232 exit(EXIT_FAILURE);
1233 }
1234
1235 odp_init_param_init(&init_param);
1236 init_param.mem_model = helper_options.mem_model;
1237
1238 if (odp_init_global(&instance, &init_param, NULL)) {
1239 ODPH_ERR("Global init failed\n");
1240 exit(EXIT_FAILURE);
1241 }
1242
1243 if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
1244 ODPH_ERR("Local init failed\n");
1245 exit(EXIT_FAILURE);
1246 }
1247
1248 shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0);
1249
1250 if (shm == ODP_SHM_INVALID) {
1251 ODPH_ERR("Shared memory reserve failed\n");
1252 exit(EXIT_FAILURE);
1253 }
1254
1255 gbl_args = odp_shm_addr(shm);
1256
1257 if (gbl_args == NULL) {
1258 ODPH_ERR("Shared memory allocation failed\n");
1259 exit(EXIT_FAILURE);
1260 }
1261
1262 memset(gbl_args, 0, sizeof(args_t));
1263 set_defaults();
1264 parse_args(argc, argv);
1265 init_suite(gbl_args);
1266
1267 if (setup_sig_handler()) {
1268 ODPH_ERR("Signal handler setup failed\n");
1269 exit(EXIT_FAILURE);
1270 }
1271
1272 if (odp_cpumask_default_worker(&default_mask, 1) != 1) {
1273 ODPH_ERR("Unable to allocate worker thread\n");
1274 exit(EXIT_FAILURE);
1275 }
1276
1277 (void)odp_cpumask_to_str(&default_mask, gbl_args->cpumask_str,
1278 sizeof(gbl_args->cpumask_str));
1279
1280 if (create_resources())
1281 exit(EXIT_FAILURE);
1282
1283 print_info();
1284 run_worker(instance, default_mask);
1285 ret = *gbl_args->suite.retval;
1286
1287 if (ret == 0 && common_options.is_export) {
1288 if (gbl_args->suite.export_fn(gbl_args)) {
1289 ODPH_ERR("Export failed\n");
1290 ret = -1;
1291 }
1292 }
1293
1294 teardown_resources();
1295
1296 if (odp_shm_free(shm)) {
1297 ODPH_ERR("Shared memory free failed\n");
1298 exit(EXIT_FAILURE);
1299 }
1300
1301 if (odp_term_local()) {
1302 ODPH_ERR("Local term local\n");
1303 exit(EXIT_FAILURE);
1304 }
1305
1306 if (odp_term_global(instance)) {
1307 ODPH_ERR("Global term global\n");
1308 exit(EXIT_FAILURE);
1309 }
1310
1311 return ret;
1312}
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
odp_event_t odp_buffer_to_event(odp_buffer_t buf)
Convert buffer handle to event.
odp_buffer_t odp_buffer_alloc(odp_pool_t pool)
Buffer alloc.
#define ODP_BUFFER_INVALID
Invalid buffer.
#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_...
void odp_event_free(odp_event_t event)
Free event.
#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_BUFFER
Buffer pool.
void * odp_queue_context(odp_queue_t queue)
Get queue context.
int odp_queue_context_set(odp_queue_t queue, void *context, uint32_t len)
Set queue context.
int odp_queue_enq_multi(odp_queue_t queue, const odp_event_t events[], int num)
Enqueue multiple events to a queue.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
int odp_queue_capability(odp_queue_capability_t *capa)
Query queue capabilities.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
int odp_queue_enq(odp_queue_t queue, odp_event_t ev)
Enqueue an event to 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.
int odp_queue_deq_multi(odp_queue_t queue, odp_event_t events[], int num)
Dequeue multiple events from a queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
@ ODP_QUEUE_OP_MT_UNSAFE
Not multithread safe operation.
int odp_schedule_multi_no_wait(odp_queue_t *from, odp_event_t events[], int num)
Schedule, do not wait for events.
int odp_schedule_multi(odp_queue_t *from, uint64_t wait, odp_event_t events[], int num)
Schedule multiple events.
#define ODP_SCHED_NO_WAIT
Do not wait.
void odp_schedule_prefetch(int num)
Prefetch events for next schedule call.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
int odp_schedule_multi_wait(odp_queue_t *from, odp_event_t events[], int num)
Schedule, wait for events.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
int odp_schedule_capability(odp_schedule_capability_t *capa)
Query scheduler capabilities.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
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.
bool odp_bool_t
Boolean type.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
The OpenDataPlane API.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
uint32_t max_num
Maximum number of buffers of any size.
struct odp_pool_capability_t::@133 buf
Buffer pool capabilities
uint32_t max_size
Maximum buffer data size in bytes.
uint32_t num
Number of buffers in the pool.
uint32_t size
Minimum buffer size in bytes.
odp_pool_type_t type
Pool type.
struct odp_pool_param_t::@138 buf
Parameters for buffer pools.
struct odp_queue_capability_t::@155 plain
Plain queue capabilities.
uint32_t max_size
Maximum number of events a plain (ODP_BLOCKING) queue can store simultaneously.
uint32_t max_num
Maximum number of plain (ODP_BLOCKING) queues of the default size.
uint32_t max_queues
Maximum number of event queues of any type (default size).
ODP Queue parameters.
odp_queue_op_mode_t enq_mode
Enqueue mode.
uint32_t size
Queue size.
odp_queue_type_t type
Queue type.
void * context
Queue context pointer.
odp_queue_op_mode_t deq_mode
Dequeue mode.
uint32_t max_queues
Maximum number of scheduled (ODP_BLOCKING) queues of the default size.
uint32_t max_queue_size
Maximum number of events a scheduled (ODP_BLOCKING) queue can store simultaneously.