API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_bench_buffer.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2017-2018 Linaro Limited
3 * Copyright (c) 2022-2025 Nokia
4 */
5
14#include <odp_api.h>
15#include <odp/helper/odph_api.h>
16
17#include <bench_common.h>
18#include <export_results.h>
19
20#include <getopt.h>
21#include <inttypes.h>
22#include <signal.h>
23#include <stdlib.h>
24#include <unistd.h>
25
27#define TEST_BUF_SIZE 1024
28
30#define TEST_UAREA_SIZE 8
31
33#define TEST_REPEAT_COUNT 1000
34
36#define TEST_ROUNDS 100u
37
39#define TEST_MAX_BURST 64
40
42#define TEST_DEF_BURST 8
43
45#define TEST_MAX_BENCH 40
46
48#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
49 strrchr((file_name), '/') + 1 : (file_name))
50
51#define BENCH_INFO(run_fn, init_fn, term_fn, alt_name) \
52 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .desc = alt_name}
53
54#define BENCH_INFO_COND(run_fn, init_fn, term_fn, alt_name, cond_fn) \
55 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .desc = alt_name, \
56 .cond = cond_fn}
57
58#define BENCH_INFO_TM(run_fn, init_fn, term_fn, cond_fn) \
59 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .cond = cond_fn,\
60 .max_rounds = 0}
61
62typedef enum {
63 M_TPUT,
64 M_LATENCY
65} meas_mode_t;
66
70typedef struct {
71 int bench_idx;
72 int burst_size;
73 int cache_size;
74 int time;
75 meas_mode_t mode;
76 uint32_t rounds;
77} appl_args_t;
78
82typedef struct {
84 appl_args_t appl;
85
87 struct {
88 union {
90 bench_suite_t b;
92 bench_tm_suite_t t;
93 };
94
96 odp_atomic_u32_t *exit;
98 int *retval;
100 void *args;
102 int (*suite_fn)(void *args);
104 int (*export_fn)(void *data);
105 } suite;
106
108 odp_pool_t pool;
110 uint32_t buf_size;
112 uint32_t uarea_size;
114 uint32_t max_flow_id;
116 odp_buffer_t buf_tbl[TEST_REPEAT_COUNT * TEST_MAX_BURST];
118 odp_event_t event_tbl[TEST_REPEAT_COUNT * TEST_MAX_BURST];
120 void *ptr_tbl[TEST_REPEAT_COUNT];
122 odp_pool_t pool_tbl[TEST_REPEAT_COUNT];
124 odp_event_type_t event_type_tbl[TEST_REPEAT_COUNT * TEST_MAX_BURST];
126 odp_event_subtype_t event_subtype_tbl[TEST_REPEAT_COUNT * TEST_MAX_BURST];
128 char cpumask_str[ODP_CPUMASK_STR_SIZE];
130 union{
132 double b[TEST_MAX_BENCH];
134 bench_tm_result_t t[TEST_MAX_BENCH];
135 } result;
136} args_t;
137
139static args_t *gbl_args;
140
141static void sig_handler(int signo ODP_UNUSED)
142{
143 if (gbl_args == NULL)
144 return;
145 odp_atomic_store_u32(gbl_args->suite.exit, 1);
146}
147
148static void allocate_test_buffers(odp_buffer_t buf[], int num)
149{
150 int num_buf = 0;
151
152 while (num_buf < num) {
153 int ret;
154
155 ret = odp_buffer_alloc_multi(gbl_args->pool, &buf[num_buf], num - num_buf);
156 if (ret < 0)
157 ODPH_ABORT("Allocating test buffers failed\n");
158
159 num_buf += ret;
160 }
161}
162
163static void create_buffers(void)
164{
165 allocate_test_buffers(gbl_args->buf_tbl, TEST_REPEAT_COUNT);
166}
167
168static void create_buffers_multi(void)
169{
170 allocate_test_buffers(gbl_args->buf_tbl, TEST_REPEAT_COUNT * gbl_args->appl.burst_size);
171}
172
173static void create_events(void)
174{
175 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
176
177 allocate_test_buffers(gbl_args->buf_tbl, TEST_REPEAT_COUNT);
178
179 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
180 gbl_args->event_tbl[i] = odp_buffer_to_event(buf_tbl[i]);
181}
182
183static void create_events_multi(void)
184{
185 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
186
187 allocate_test_buffers(gbl_args->buf_tbl,
188 TEST_REPEAT_COUNT * gbl_args->appl.burst_size);
189
190 for (int i = 0; i < TEST_REPEAT_COUNT * gbl_args->appl.burst_size; i++)
191 gbl_args->event_tbl[i] = odp_buffer_to_event(buf_tbl[i]);
192}
193
194static void free_buffers(void)
195{
196 odp_buffer_free_multi(gbl_args->buf_tbl, TEST_REPEAT_COUNT);
197}
198
199static void free_buffers_multi(void)
200{
201 odp_buffer_free_multi(gbl_args->buf_tbl, TEST_REPEAT_COUNT * gbl_args->appl.burst_size);
202}
203
204static int check_uarea(void)
205{
206 return !!gbl_args->uarea_size;
207}
208
209static int check_flow_aware(void)
210{
211 return !!gbl_args->max_flow_id;
212}
213
214static int buffer_from_event(void)
215{
216 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
217 odp_event_t *event_tbl = gbl_args->event_tbl;
218 int i;
219
220 for (i = 0; i < TEST_REPEAT_COUNT; i++)
221 buf_tbl[i] = odp_buffer_from_event(event_tbl[i]);
222
223 return i;
224}
225
226static int buffer_from_event_tm(bench_tm_result_t *res, int repeat_count)
227{
228 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
229 odp_event_t *event_tbl = gbl_args->event_tbl;
230 int i;
231 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_from_event()");
232 bench_tm_stamp_t s1, s2;
233
234 for (i = 0; i < repeat_count; i++) {
235 bench_tm_now(res, &s1);
236 buf_tbl[i] = odp_buffer_from_event(event_tbl[i]);
237 bench_tm_now(res, &s2);
238 bench_tm_func_record(&s2, &s1, res, id1);
239 }
240
241 return i;
242}
243
244static int buffer_from_event_multi(void)
245{
246 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
247 odp_event_t *event_tbl = gbl_args->event_tbl;
248 int burst_size = gbl_args->appl.burst_size;
249 int i;
250
251 for (i = 0; i < TEST_REPEAT_COUNT; i++)
252 odp_buffer_from_event_multi(&buf_tbl[i * burst_size],
253 &event_tbl[i * burst_size], burst_size);
254
255 return i;
256}
257
258static int buffer_from_event_multi_tm(bench_tm_result_t *res, int repeat_count)
259{
260 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
261 odp_event_t *event_tbl = gbl_args->event_tbl;
262 int burst_size = gbl_args->appl.burst_size;
263 int i;
264 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_from_event_multi()");
265 bench_tm_stamp_t s1, s2;
266
267 for (i = 0; i < repeat_count; i++) {
268 bench_tm_now(res, &s1);
269 odp_buffer_from_event_multi(&buf_tbl[i * burst_size],
270 &event_tbl[i * burst_size], burst_size);
271 bench_tm_now(res, &s2);
272 bench_tm_func_record(&s2, &s1, res, id1);
273 }
274
275 return i;
276}
277
278static int buffer_to_event(void)
279{
280 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
281 odp_event_t *event_tbl = gbl_args->event_tbl;
282 int i;
283
284 for (i = 0; i < TEST_REPEAT_COUNT; i++)
285 event_tbl[i] = odp_buffer_to_event(buf_tbl[i]);
286
287 return i;
288}
289
290static int buffer_to_event_tm(bench_tm_result_t *res, int repeat_count)
291{
292 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
293 odp_event_t *event_tbl = gbl_args->event_tbl;
294 int i;
295 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_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 event_tbl[i] = odp_buffer_to_event(buf_tbl[i]);
301 bench_tm_now(res, &s2);
302 bench_tm_func_record(&s2, &s1, res, id1);
303 }
304
305 return i;
306}
307
308static int buffer_to_event_multi(void)
309{
310 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
311 odp_event_t *event_tbl = gbl_args->event_tbl;
312 int burst_size = gbl_args->appl.burst_size;
313 int i;
314
315 for (i = 0; i < TEST_REPEAT_COUNT; i++)
316 odp_buffer_to_event_multi(&buf_tbl[i * burst_size],
317 &event_tbl[i * burst_size], burst_size);
318
319 return i;
320}
321
322static int buffer_to_event_multi_tm(bench_tm_result_t *res, int repeat_count)
323{
324 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
325 odp_event_t *event_tbl = gbl_args->event_tbl;
326 int burst_size = gbl_args->appl.burst_size;
327 int i;
328 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_to_event_multi()");
329 bench_tm_stamp_t s1, s2;
330
331 for (i = 0; i < repeat_count; i++) {
332 bench_tm_now(res, &s1);
333 odp_buffer_to_event_multi(&buf_tbl[i * burst_size],
334 &event_tbl[i * burst_size], burst_size);
335 bench_tm_now(res, &s2);
336 bench_tm_func_record(&s2, &s1, res, id1);
337 }
338
339 return i;
340}
341
342static int buffer_addr(void)
343{
344 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
345 void **ptr_tbl = gbl_args->ptr_tbl;
346 int i;
347
348 for (i = 0; i < TEST_REPEAT_COUNT; i++)
349 ptr_tbl[i] = odp_buffer_addr(buf_tbl[i]);
350
351 return i;
352}
353
354static int buffer_addr_tm(bench_tm_result_t *res, int repeat_count)
355{
356 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
357 void **ptr_tbl = gbl_args->ptr_tbl;
358 int i;
359 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_addr()");
360 bench_tm_stamp_t s1, s2;
361
362 for (i = 0; i < repeat_count; i++) {
363 bench_tm_now(res, &s1);
364 ptr_tbl[i] = odp_buffer_addr(buf_tbl[i]);
365 bench_tm_now(res, &s2);
366 bench_tm_func_record(&s2, &s1, res, id1);
367 }
368
369 return i;
370}
371
372static int buffer_size(void)
373{
374 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
375 uint32_t ret = 0;
376
377 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
378 ret += odp_buffer_size(buf_tbl[i]);
379
380 return ret;
381}
382
383static int buffer_size_tm(bench_tm_result_t *res, int repeat_count)
384{
385 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
386 uint32_t ret = 0;
387 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_size()");
388 bench_tm_stamp_t s1, s2;
389
390 for (int i = 0; i < repeat_count; i++) {
391 bench_tm_now(res, &s1);
392 ret += odp_buffer_size(buf_tbl[i]);
393 bench_tm_now(res, &s2);
394 bench_tm_func_record(&s2, &s1, res, id1);
395 }
396
397 return ret;
398}
399
400static int buffer_user_area(void)
401{
402 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
403 void **ptr_tbl = gbl_args->ptr_tbl;
404 int i;
405
406 for (i = 0; i < TEST_REPEAT_COUNT; i++)
407 ptr_tbl[i] = odp_buffer_user_area(buf_tbl[i]);
408
409 return i;
410}
411
412static int buffer_user_area_tm(bench_tm_result_t *res, int repeat_count)
413{
414 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
415 void **ptr_tbl = gbl_args->ptr_tbl;
416 int i;
417 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_user_area()");
418 bench_tm_stamp_t s1, s2;
419
420 for (i = 0; i < repeat_count; i++) {
421 bench_tm_now(res, &s1);
422 ptr_tbl[i] = odp_buffer_user_area(buf_tbl[i]);
423 bench_tm_now(res, &s2);
424 bench_tm_func_record(&s2, &s1, res, id1);
425 }
426
427 return i;
428}
429
430static int buffer_pool(void)
431{
432 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
433 odp_pool_t *pool_tbl = gbl_args->pool_tbl;
434 int i;
435
436 for (i = 0; i < TEST_REPEAT_COUNT; i++)
437 pool_tbl[i] = odp_buffer_pool(buf_tbl[i]);
438
439 return i;
440}
441
442static int buffer_pool_tm(bench_tm_result_t *res, int repeat_count)
443{
444 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
445 odp_pool_t *pool_tbl = gbl_args->pool_tbl;
446 int i;
447 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_pool()");
448 bench_tm_stamp_t s1, s2;
449
450 for (i = 0; i < repeat_count; i++) {
451 bench_tm_now(res, &s1);
452 pool_tbl[i] = odp_buffer_pool(buf_tbl[i]);
453 bench_tm_now(res, &s2);
454 bench_tm_func_record(&s2, &s1, res, id1);
455 }
456
457 return i;
458}
459
460static int buffer_alloc(void)
461{
462 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
463 odp_pool_t pool = gbl_args->pool;
464 int i;
465
466 for (i = 0; i < TEST_REPEAT_COUNT; i++)
467 buf_tbl[i] = odp_buffer_alloc(pool);
468
469 return i;
470}
471
472static int buffer_alloc_tm(bench_tm_result_t *res, int repeat_count)
473{
474 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
475 odp_pool_t pool = gbl_args->pool;
476 int i;
477 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_alloc()");
478 bench_tm_stamp_t s1, s2;
479
480 for (i = 0; i < repeat_count; i++) {
481 bench_tm_now(res, &s1);
482 buf_tbl[i] = odp_buffer_alloc(pool);
483 bench_tm_now(res, &s2);
484 bench_tm_func_record(&s2, &s1, res, id1);
485 }
486
487 return i;
488}
489
490static int buffer_alloc_multi(void)
491{
492 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
493 odp_pool_t pool = gbl_args->pool;
494 int burst_size = gbl_args->appl.burst_size;
495 int num = 0;
496
497 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
498 num += odp_buffer_alloc_multi(pool, &buf_tbl[num], burst_size);
499
500 return num;
501}
502
503static int buffer_alloc_multi_tm(bench_tm_result_t *res, int repeat_count)
504{
505 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
506 odp_pool_t pool = gbl_args->pool;
507 int burst_size = gbl_args->appl.burst_size;
508 int num = 0;
509 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_alloc_multi()");
510 bench_tm_stamp_t s1, s2;
511
512 for (int i = 0; i < repeat_count; i++) {
513 bench_tm_now(res, &s1);
514 num += odp_buffer_alloc_multi(pool, &buf_tbl[num], burst_size);
515 bench_tm_now(res, &s2);
516 bench_tm_func_record(&s2, &s1, res, id1);
517 }
518
519 return num;
520}
521
522static int buffer_free(void)
523{
524 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
525 int i;
526
527 for (i = 0; i < TEST_REPEAT_COUNT; i++)
528 odp_buffer_free(buf_tbl[i]);
529
530 return i;
531}
532
533static int buffer_free_tm(bench_tm_result_t *res, int repeat_count)
534{
535 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
536 int i;
537 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_free()");
538 bench_tm_stamp_t s1, s2;
539
540 for (i = 0; i < repeat_count; i++) {
541 bench_tm_now(res, &s1);
542 odp_buffer_free(buf_tbl[i]);
543 bench_tm_now(res, &s2);
544 bench_tm_func_record(&s2, &s1, res, id1);
545 }
546
547 return i;
548}
549
550static int buffer_free_multi(void)
551{
552 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
553 int burst_size = gbl_args->appl.burst_size;
554 int i;
555
556 for (i = 0; i < TEST_REPEAT_COUNT; i++)
557 odp_buffer_free_multi(&buf_tbl[i * burst_size], burst_size);
558
559 return i;
560}
561
562static int buffer_free_multi_tm(bench_tm_result_t *res, int repeat_count)
563{
564 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
565 int burst_size = gbl_args->appl.burst_size;
566 int i;
567 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_free_multi()");
568 bench_tm_stamp_t s1, s2;
569
570 for (i = 0; i < repeat_count; i++) {
571 bench_tm_now(res, &s1);
572 odp_buffer_free_multi(&buf_tbl[i * burst_size], burst_size);
573 bench_tm_now(res, &s2);
574 bench_tm_func_record(&s2, &s1, res, id1);
575 }
576
577 return i;
578}
579
580static int buffer_alloc_free(void)
581{
582 odp_pool_t pool = gbl_args->pool;
583 int i;
584
585 for (i = 0; i < TEST_REPEAT_COUNT; i++) {
586 odp_buffer_t buf = odp_buffer_alloc(pool);
587
589 return 0;
590
591 odp_buffer_free(buf);
592 }
593 return i;
594}
595
596static int buffer_alloc_free_tm(bench_tm_result_t *res, int repeat_count)
597{
598 odp_pool_t pool = gbl_args->pool;
599 int i;
600 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_alloc()/_free()");
601 bench_tm_stamp_t s1, s2;
602
603 for (i = 0; i < repeat_count; i++) {
604 bench_tm_now(res, &s1);
605 odp_buffer_t buf = odp_buffer_alloc(pool);
606
607 ODPH_ASSERT(buf != ODP_BUFFER_INVALID);
608
609 odp_buffer_free(buf);
610 bench_tm_now(res, &s2);
611 bench_tm_func_record(&s2, &s1, res, id1);
612 }
613
614 return i;
615}
616
617static int buffer_alloc_free_multi(void)
618{
619 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
620 odp_pool_t pool = gbl_args->pool;
621 int burst_size = gbl_args->appl.burst_size;
622 int i;
623
624 for (i = 0; i < TEST_REPEAT_COUNT; i++) {
625 int num = odp_buffer_alloc_multi(pool, buf_tbl, burst_size);
626
627 if (odp_unlikely(num < 1))
628 return 0;
629
630 odp_buffer_free_multi(buf_tbl, num);
631 }
632 return i;
633}
634
635static int buffer_alloc_free_multi_tm(bench_tm_result_t *res, int repeat_count)
636{
637 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
638 odp_pool_t pool = gbl_args->pool;
639 int burst_size = gbl_args->appl.burst_size;
640 int i;
641 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_alloc_multi()/_free_multi()");
642 bench_tm_stamp_t s1, s2;
643
644 for (i = 0; i < repeat_count; i++) {
645 bench_tm_now(res, &s1);
646 int num = odp_buffer_alloc_multi(pool, buf_tbl, burst_size);
647
648 ODPH_ASSERT(num >= 1);
649
650 odp_buffer_free_multi(buf_tbl, num);
651 bench_tm_now(res, &s2);
652 bench_tm_func_record(&s2, &s1, res, id1);
653 }
654
655 return i;
656}
657
658static int buffer_is_valid(void)
659{
660 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
661 uint32_t ret = 0;
662
663 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
664 ret += odp_buffer_is_valid(buf_tbl[i]);
665
666 return ret;
667}
668
669static int buffer_is_valid_tm(bench_tm_result_t *res, int repeat_count)
670{
671 odp_buffer_t *buf_tbl = gbl_args->buf_tbl;
672 uint32_t ret = 0;
673 const uint8_t id1 = bench_tm_func_register(res, "odp_buffer_is_valid()");
674 bench_tm_stamp_t s1, s2;
675
676 for (int i = 0; i < repeat_count; i++) {
677 bench_tm_now(res, &s1);
678 ret += odp_buffer_is_valid(buf_tbl[i]);
679 bench_tm_now(res, &s2);
680 bench_tm_func_record(&s2, &s1, res, id1);
681 }
682
683 return ret;
684}
685
686static int event_type(void)
687{
688 odp_event_t *event_tbl = gbl_args->event_tbl;
689 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
690 int i;
691
692 for (i = 0; i < TEST_REPEAT_COUNT; i++)
693 event_type_tbl[i] = odp_event_type(event_tbl[i]);
694
695 return i;
696}
697
698static int event_type_tm(bench_tm_result_t *res, int repeat_count)
699{
700 odp_event_t *event_tbl = gbl_args->event_tbl;
701 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
702 int i;
703 const uint8_t id1 = bench_tm_func_register(res, "odp_event_type()");
704 bench_tm_stamp_t s1, s2;
705
706 for (i = 0; i < repeat_count; i++) {
707 bench_tm_now(res, &s1);
708 event_type_tbl[i] = odp_event_type(event_tbl[i]);
709 bench_tm_now(res, &s2);
710 bench_tm_func_record(&s2, &s1, res, id1);
711 }
712
713 return i;
714}
715
716static int event_subtype(void)
717{
718 odp_event_t *event_tbl = gbl_args->event_tbl;
719 odp_event_subtype_t *event_subtype_tbl = gbl_args->event_subtype_tbl;
720 int i;
721
722 for (i = 0; i < TEST_REPEAT_COUNT; i++)
723 event_subtype_tbl[i] = odp_event_subtype(event_tbl[i]);
724
725 return i;
726}
727
728static int event_subtype_tm(bench_tm_result_t *res, int repeat_count)
729{
730 odp_event_t *event_tbl = gbl_args->event_tbl;
731 odp_event_subtype_t *event_subtype_tbl = gbl_args->event_subtype_tbl;
732 int i;
733 const uint8_t id1 = bench_tm_func_register(res, "odp_event_subtype()");
734 bench_tm_stamp_t s1, s2;
735
736 for (i = 0; i < repeat_count; i++) {
737 bench_tm_now(res, &s1);
738 event_subtype_tbl[i] = odp_event_subtype(event_tbl[i]);
739 bench_tm_now(res, &s2);
740 bench_tm_func_record(&s2, &s1, res, id1);
741 }
742
743 return i;
744}
745
746static int event_types(void)
747{
748 odp_event_t *event_tbl = gbl_args->event_tbl;
749 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
750 odp_event_subtype_t *event_subtype_tbl = gbl_args->event_subtype_tbl;
751 int i;
752
753 for (i = 0; i < TEST_REPEAT_COUNT; i++)
754 event_type_tbl[i] = odp_event_types(event_tbl[i], &event_subtype_tbl[i]);
755
756 return i;
757}
758
759static int event_types_tm(bench_tm_result_t *res, int repeat_count)
760{
761 odp_event_t *event_tbl = gbl_args->event_tbl;
762 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
763 odp_event_subtype_t *event_subtype_tbl = gbl_args->event_subtype_tbl;
764 int i;
765 const uint8_t id1 = bench_tm_func_register(res, "odp_event_types()");
766 bench_tm_stamp_t s1, s2;
767
768 for (i = 0; i < repeat_count; i++) {
769 bench_tm_now(res, &s1);
770 event_type_tbl[i] = odp_event_types(event_tbl[i], &event_subtype_tbl[i]);
771 bench_tm_now(res, &s2);
772 bench_tm_func_record(&s2, &s1, res, id1);
773 }
774
775 return i;
776}
777
778static int event_types_multi(void)
779{
780 odp_event_t *event_tbl = gbl_args->event_tbl;
781 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
782 odp_event_subtype_t *event_subtype_tbl = gbl_args->event_subtype_tbl;
783 int burst_size = gbl_args->appl.burst_size;
784 int i;
785
786 for (i = 0; i < TEST_REPEAT_COUNT; i++)
787 odp_event_types_multi(&event_tbl[i * burst_size],
788 &event_type_tbl[i * burst_size],
789 &event_subtype_tbl[i * burst_size], burst_size);
790
791 return i;
792}
793
794static int event_types_multi_tm(bench_tm_result_t *res, int repeat_count)
795{
796 odp_event_t *event_tbl = gbl_args->event_tbl;
797 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
798 odp_event_subtype_t *event_subtype_tbl = gbl_args->event_subtype_tbl;
799 int burst_size = gbl_args->appl.burst_size;
800 int i;
801 const uint8_t id1 = bench_tm_func_register(res, "odp_event_types_multi()");
802 bench_tm_stamp_t s1, s2;
803
804 for (i = 0; i < repeat_count; i++) {
805 bench_tm_now(res, &s1);
806 odp_event_types_multi(&event_tbl[i * burst_size],
807 &event_type_tbl[i * burst_size],
808 &event_subtype_tbl[i * burst_size], burst_size);
809 bench_tm_now(res, &s2);
810 bench_tm_func_record(&s2, &s1, res, id1);
811 }
812
813 return i;
814}
815
816static int event_types_multi_no_sub(void)
817{
818 odp_event_t *event_tbl = gbl_args->event_tbl;
819 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
820 int burst_size = gbl_args->appl.burst_size;
821 int i;
822
823 for (i = 0; i < TEST_REPEAT_COUNT; i++)
824 odp_event_types_multi(&event_tbl[i * burst_size],
825 &event_type_tbl[i * burst_size], NULL, burst_size);
826
827 return i;
828}
829
830static int event_types_multi_no_sub_tm(bench_tm_result_t *res, int repeat_count)
831{
832 odp_event_t *event_tbl = gbl_args->event_tbl;
833 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
834 int burst_size = gbl_args->appl.burst_size;
835 int i;
836 const uint8_t id1 = bench_tm_func_register(res, "odp_event_types_multi()");
837 bench_tm_stamp_t s1, s2;
838
839 for (i = 0; i < repeat_count; i++) {
840 bench_tm_now(res, &s1);
841 odp_event_types_multi(&event_tbl[i * burst_size],
842 &event_type_tbl[i * burst_size], NULL, burst_size);
843 bench_tm_now(res, &s2);
844 bench_tm_func_record(&s2, &s1, res, id1);
845 }
846
847 return i;
848}
849
850static int event_type_multi(void)
851{
852 odp_event_t *event_tbl = gbl_args->event_tbl;
853 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
854 int burst_size = gbl_args->appl.burst_size;
855 uint32_t ret = 0;
856
857 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
858 ret += odp_event_type_multi(&event_tbl[i * burst_size], burst_size,
859 &event_type_tbl[i]);
860
861 return ret;
862}
863
864static int event_type_multi_tm(bench_tm_result_t *res, int repeat_count)
865{
866 odp_event_t *event_tbl = gbl_args->event_tbl;
867 odp_event_type_t *event_type_tbl = gbl_args->event_type_tbl;
868 int burst_size = gbl_args->appl.burst_size;
869 uint32_t ret = 0;
870 const uint8_t id1 = bench_tm_func_register(res, "odp_event_type_multi()");
871 bench_tm_stamp_t s1, s2;
872
873 for (int i = 0; i < repeat_count; i++) {
874 bench_tm_now(res, &s1);
875 ret += odp_event_type_multi(&event_tbl[i * burst_size], burst_size,
876 &event_type_tbl[i]);
877 bench_tm_now(res, &s2);
878 bench_tm_func_record(&s2, &s1, res, id1);
879 }
880
881 return ret;
882}
883
884static int event_pool(void)
885{
886 odp_event_t *event_tbl = gbl_args->event_tbl;
887 odp_pool_t *pool_tbl = gbl_args->pool_tbl;
888 int i;
889
890 for (i = 0; i < TEST_REPEAT_COUNT; i++)
891 pool_tbl[i] = odp_event_pool(event_tbl[i]);
892
893 return i;
894}
895
896static int event_pool_tm(bench_tm_result_t *res, int repeat_count)
897{
898 odp_event_t *event_tbl = gbl_args->event_tbl;
899 odp_pool_t *pool_tbl = gbl_args->pool_tbl;
900 int i;
901 const uint8_t id1 = bench_tm_func_register(res, "odp_event_pool()");
902 bench_tm_stamp_t s1, s2;
903
904 for (i = 0; i < repeat_count; i++) {
905 bench_tm_now(res, &s1);
906 pool_tbl[i] = odp_event_pool(event_tbl[i]);
907 bench_tm_now(res, &s2);
908 bench_tm_func_record(&s2, &s1, res, id1);
909 }
910
911 return i;
912}
913
914static int event_user_area(void)
915{
916 odp_event_t *event_tbl = gbl_args->event_tbl;
917 void **ptr_tbl = gbl_args->ptr_tbl;
918 int i;
919
920 for (i = 0; i < TEST_REPEAT_COUNT; i++)
921 ptr_tbl[i] = odp_event_user_area(event_tbl[i]);
922
923 return i;
924}
925
926static int event_user_area_tm(bench_tm_result_t *res, int repeat_count)
927{
928 odp_event_t *event_tbl = gbl_args->event_tbl;
929 void **ptr_tbl = gbl_args->ptr_tbl;
930 int i;
931 const uint8_t id1 = bench_tm_func_register(res, "odp_event_user_area()");
932 bench_tm_stamp_t s1, s2;
933
934 for (i = 0; i < repeat_count; i++) {
935 bench_tm_now(res, &s1);
936 ptr_tbl[i] = odp_event_user_area(event_tbl[i]);
937 bench_tm_now(res, &s2);
938 bench_tm_func_record(&s2, &s1, res, id1);
939 }
940
941 return i;
942}
943
944static int event_user_area_and_flag(void)
945{
946 odp_event_t *event_tbl = gbl_args->event_tbl;
947 void **ptr_tbl = gbl_args->ptr_tbl;
948 int ret = 0;
949 int flag;
950
951 for (int i = 0; i < TEST_REPEAT_COUNT; i++) {
952 ptr_tbl[i] = odp_event_user_area_and_flag(event_tbl[i], &flag);
953 ret += flag;
954 }
955
956 return ret;
957}
958
959static int event_user_area_and_flag_tm(bench_tm_result_t *res, int repeat_count)
960{
961 odp_event_t *event_tbl = gbl_args->event_tbl;
962 void **ptr_tbl = gbl_args->ptr_tbl;
963 int ret = 0;
964 int flag;
965 const uint8_t id1 = bench_tm_func_register(res, "odp_event_user_area_and_flag()");
966 bench_tm_stamp_t s1, s2;
967
968 for (int i = 0; i < repeat_count; i++) {
969 bench_tm_now(res, &s1);
970 ptr_tbl[i] = odp_event_user_area_and_flag(event_tbl[i], &flag);
971 bench_tm_now(res, &s2);
972 bench_tm_func_record(&s2, &s1, res, id1);
973 ret += flag;
974 }
975
976 return ret;
977}
978
979static int event_is_valid(void)
980{
981 odp_event_t *event_tbl = gbl_args->event_tbl;
982
983 uint32_t ret = 0;
984
985 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
986 ret += odp_event_is_valid(event_tbl[i]);
987
988 return ret;
989}
990
991static int event_is_valid_tm(bench_tm_result_t *res, int repeat_count)
992{
993 odp_event_t *event_tbl = gbl_args->event_tbl;
994 uint32_t ret = 0;
995 const uint8_t id1 = bench_tm_func_register(res, "odp_event_is_valid()");
996 bench_tm_stamp_t s1, s2;
997
998 for (int i = 0; i < repeat_count; i++) {
999 bench_tm_now(res, &s1);
1000 ret += odp_event_is_valid(event_tbl[i]);
1001 bench_tm_now(res, &s2);
1002 bench_tm_func_record(&s2, &s1, res, id1);
1003 }
1004
1005 return ret;
1006}
1007
1008static int event_free(void)
1009{
1010 odp_event_t *event_tbl = gbl_args->event_tbl;
1011
1012 int i;
1013
1014 for (i = 0; i < TEST_REPEAT_COUNT; i++)
1015 odp_event_free(event_tbl[i]);
1016
1017 return i;
1018}
1019
1020static int event_free_tm(bench_tm_result_t *res, int repeat_count)
1021{
1022 odp_event_t *event_tbl = gbl_args->event_tbl;
1023 int i;
1024 const uint8_t id1 = bench_tm_func_register(res, "odp_event_free()");
1025 bench_tm_stamp_t s1, s2;
1026
1027 for (i = 0; i < repeat_count; i++) {
1028 bench_tm_now(res, &s1);
1029 odp_event_free(event_tbl[i]);
1030 bench_tm_now(res, &s2);
1031 bench_tm_func_record(&s2, &s1, res, id1);
1032 }
1033
1034 return i;
1035}
1036
1037static int event_free_multi(void)
1038{
1039 odp_event_t *event_tbl = gbl_args->event_tbl;
1040 int burst_size = gbl_args->appl.burst_size;
1041 int i;
1042
1043 for (i = 0; i < TEST_REPEAT_COUNT; i++)
1044 odp_event_free_multi(&event_tbl[i * burst_size], burst_size);
1045
1046 return i;
1047}
1048
1049static int event_free_multi_tm(bench_tm_result_t *res, int repeat_count)
1050{
1051 odp_event_t *event_tbl = gbl_args->event_tbl;
1052 int burst_size = gbl_args->appl.burst_size;
1053 int i;
1054 const uint8_t id1 = bench_tm_func_register(res, "odp_event_free_multi()");
1055 bench_tm_stamp_t s1, s2;
1056
1057 for (i = 0; i < repeat_count; i++) {
1058 bench_tm_now(res, &s1);
1059 odp_event_free_multi(&event_tbl[i * burst_size], burst_size);
1060 bench_tm_now(res, &s2);
1061 bench_tm_func_record(&s2, &s1, res, id1);
1062 }
1063
1064 return i;
1065}
1066
1067static int event_free_sp(void)
1068{
1069 odp_event_t *event_tbl = gbl_args->event_tbl;
1070 int burst_size = gbl_args->appl.burst_size;
1071 int i;
1072
1073 for (i = 0; i < TEST_REPEAT_COUNT; i++)
1074 odp_event_free_sp(&event_tbl[i * burst_size], burst_size);
1075
1076 return i;
1077}
1078
1079static int event_free_sp_tm(bench_tm_result_t *res, int repeat_count)
1080{
1081 odp_event_t *event_tbl = gbl_args->event_tbl;
1082 int burst_size = gbl_args->appl.burst_size;
1083 int i;
1084 const uint8_t id1 = bench_tm_func_register(res, "odp_event_free_sp()");
1085 bench_tm_stamp_t s1, s2;
1086
1087 for (i = 0; i < repeat_count; i++) {
1088 bench_tm_now(res, &s1);
1089 odp_event_free_sp(&event_tbl[i * burst_size], burst_size);
1090 bench_tm_now(res, &s2);
1091 bench_tm_func_record(&s2, &s1, res, id1);
1092 }
1093
1094 return i;
1095}
1096
1097static int event_flow_id(void)
1098{
1099 odp_event_t *event_tbl = gbl_args->event_tbl;
1100 uint32_t ret = 0;
1101
1102 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
1103 ret += odp_event_flow_id(event_tbl[i]);
1104
1105 return !ret;
1106}
1107
1108static int event_flow_id_tm(bench_tm_result_t *res, int repeat_count)
1109{
1110 odp_event_t *event_tbl = gbl_args->event_tbl;
1111 uint32_t ret = 0;
1112 const uint8_t id1 = bench_tm_func_register(res, "odp_event_flow_id()");
1113 bench_tm_stamp_t s1, s2;
1114
1115 for (int i = 0; i < repeat_count; i++) {
1116 bench_tm_now(res, &s1);
1117 ret += odp_event_flow_id(event_tbl[i]);
1118 bench_tm_now(res, &s2);
1119 bench_tm_func_record(&s2, &s1, res, id1);
1120 }
1121
1122 return !ret;
1123}
1124
1125static int event_flow_id_set(void)
1126{
1127 odp_event_t *event_tbl = gbl_args->event_tbl;
1128 int i = 0;
1129
1130 for (i = 0; i < TEST_REPEAT_COUNT; i++)
1131 odp_event_flow_id_set(event_tbl[i], 0);
1132
1133 return i;
1134}
1135
1136static int event_flow_id_set_tm(bench_tm_result_t *res, int repeat_count)
1137{
1138 odp_event_t *event_tbl = gbl_args->event_tbl;
1139 int i = 0;
1140 const uint8_t id1 = bench_tm_func_register(res, "odp_event_flow_id_set()");
1141 bench_tm_stamp_t s1, s2;
1142
1143 for (i = 0; i < repeat_count; i++) {
1144 bench_tm_now(res, &s1);
1145 odp_event_flow_id_set(event_tbl[i], 0);
1146 bench_tm_now(res, &s2);
1147 bench_tm_func_record(&s2, &s1, res, id1);
1148 }
1149
1150 return i;
1151}
1152
1156static void usage(char *progname)
1157{
1158 printf("\n"
1159 "OpenDataPlane Buffer/Event API microbenchmarks.\n"
1160 "\n"
1161 "Usage: %s OPTIONS\n"
1162 " E.g. %s\n"
1163 "\n"
1164 "Optional OPTIONS:\n"
1165 " -b, --burst <num> Test burst size.\n"
1166 " -c, --cache_size <num> Pool cache size.\n"
1167 " -i, --index <idx> Benchmark index to run indefinitely.\n"
1168 " -r, --rounds <num> Run each test case 'num' times (default %u).\n"
1169 " -t, --time <opt> Time measurement. 0: measure CPU cycles (default), 1: measure time\n"
1170 " -m, --mode <mode> Measurement mode. 0: measure throughput, track average execution\n"
1171 " time (default), 1: measure latency, track function minimum and\n"
1172 " maximum in addition to average execution time.\n"
1173 " -h, --help Display help and exit.\n\n"
1174 "\n", NO_PATH(progname), NO_PATH(progname), TEST_ROUNDS);
1175}
1176
1184static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
1185{
1186 int opt;
1187 static const struct option longopts[] = {
1188 {"burst", required_argument, NULL, 'b'},
1189 {"cache_size", required_argument, NULL, 'c'},
1190 {"index", required_argument, NULL, 'i'},
1191 {"rounds", required_argument, NULL, 'r'},
1192 {"time", required_argument, NULL, 't'},
1193 {"mode", required_argument, NULL, 'm'},
1194 {"help", no_argument, NULL, 'h'},
1195 {NULL, 0, NULL, 0}
1196 };
1197
1198 static const char *shortopts = "c:b:i:r:t:m:h";
1199
1200 appl_args->bench_idx = 0; /* Run all benchmarks */
1201 appl_args->burst_size = TEST_DEF_BURST;
1202 appl_args->cache_size = -1;
1203 appl_args->rounds = TEST_ROUNDS;
1204 appl_args->time = 0;
1205 appl_args->mode = M_TPUT;
1206
1207 while (1) {
1208 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
1209
1210 if (opt == -1)
1211 break; /* No more options */
1212
1213 switch (opt) {
1214 case 'c':
1215 appl_args->cache_size = atoi(optarg);
1216 break;
1217 case 'b':
1218 appl_args->burst_size = atoi(optarg);
1219 break;
1220 case 'h':
1221 usage(argv[0]);
1222 exit(EXIT_SUCCESS);
1223 break;
1224 case 'i':
1225 appl_args->bench_idx = atoi(optarg);
1226 break;
1227 case 'r':
1228 appl_args->rounds = atoi(optarg);
1229 break;
1230 case 't':
1231 appl_args->time = atoi(optarg);
1232 break;
1233 case 'm':
1234 appl_args->mode = atoi(optarg);
1235 break;
1236 default:
1237 break;
1238 }
1239 }
1240
1241 if (appl_args->burst_size < 1 ||
1242 appl_args->burst_size > TEST_MAX_BURST) {
1243 printf("Invalid burst size (max %d)\n", TEST_MAX_BURST);
1244 exit(EXIT_FAILURE);
1245 }
1246
1247 if (appl_args->rounds < 1) {
1248 printf("Invalid number test rounds: %d\n", appl_args->rounds);
1249 exit(EXIT_FAILURE);
1250 }
1251
1252 if (appl_args->mode != M_TPUT && appl_args->mode != M_LATENCY) {
1253 printf("Invalid measurement mode: %d\n", appl_args->mode);
1254 exit(EXIT_FAILURE);
1255 }
1256
1257 optind = 1; /* Reset 'extern optind' from the getopt lib */
1258}
1259
1263static void print_info(void)
1264{
1266
1267 printf("\n"
1268 "odp_bench_buffer options\n"
1269 "------------------------\n");
1270
1271 printf("Burst size: %d\n", gbl_args->appl.burst_size);
1272 printf("Buffer size: %d\n", gbl_args->buf_size);
1273 printf("CPU mask: %s\n", gbl_args->cpumask_str);
1274 if (gbl_args->appl.cache_size < 0)
1275 printf("Pool cache size: default\n");
1276 else
1277 printf("Pool cache size: %d\n", gbl_args->appl.cache_size);
1278 printf("Measurement unit: %s\n", gbl_args->appl.time ? "nsec" : "CPU cycles");
1279 printf("Test rounds: %u\n", gbl_args->appl.rounds);
1280 printf("Measurement mode: %s\n", gbl_args->appl.mode == M_TPUT ? "throughput" : "latency");
1281 printf("\n");
1282}
1283
1284static int bench_buffer_tm_export(void *data)
1285{
1286 args_t *gbl_args = data;
1287 bench_tm_result_t *res;
1288 uint64_t num;
1289 int ret = 0;
1290 const char *unit = gbl_args->appl.time ? "nsec" : "cpu cycles";
1291
1292 if (test_common_write("function name,min %s per function call,"
1293 "average %s per function call,"
1294 "max %s per function call\n", unit, unit, unit)) {
1295 ret = -1;
1296 goto exit;
1297 }
1298
1299 for (uint32_t i = 0; i < gbl_args->suite.t.num_bench; i++) {
1300 res = &gbl_args->suite.t.result[i];
1301
1302 for (int j = 0; j < res->num; j++) {
1303 num = res->func[j].num ? res->func[j].num : 1;
1304 if (test_common_write("%s,%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
1305 res->func[j].name,
1306 bench_tm_to_u64(res, &res->func[j].min),
1307 bench_tm_to_u64(res, &res->func[j].tot) / num,
1308 bench_tm_to_u64(res, &res->func[j].max))) {
1309 ret = -1;
1310 goto exit;
1311 }
1312 }
1313 }
1314
1315exit:
1316 test_common_write_term();
1317
1318 return ret;
1319}
1320
1321static int bench_buffer_export(void *data)
1322{
1323 args_t *gbl_args = data;
1324 int ret = 0;
1325
1326 if (test_common_write("%s", gbl_args->appl.time ?
1327 "function name,average nsec per function call\n" :
1328 "function name,average cpu cycles per function call\n")) {
1329 ret = -1;
1330 goto exit;
1331 }
1332
1333 for (int i = 0; i < gbl_args->suite.b.num_bench; i++) {
1334 if (test_common_write("odp_%s,%f\n", gbl_args->suite.b.bench[i].desc != NULL ?
1335 gbl_args->suite.b.bench[i].desc :
1336 gbl_args->suite.b.bench[i].name,
1337 gbl_args->suite.b.result[i])) {
1338 ret = -1;
1339 goto exit;
1340 }
1341 }
1342
1343exit:
1344 test_common_write_term();
1345
1346 return ret;
1347}
1348
1352bench_info_t test_suite[] = {
1353 BENCH_INFO(buffer_from_event, create_events, free_buffers, NULL),
1354 BENCH_INFO(buffer_from_event_multi, create_events_multi, free_buffers_multi, NULL),
1355 BENCH_INFO(buffer_to_event, create_buffers, free_buffers, NULL),
1356 BENCH_INFO(buffer_to_event_multi, create_buffers_multi, free_buffers_multi, NULL),
1357 BENCH_INFO(buffer_addr, create_buffers, free_buffers, NULL),
1358 BENCH_INFO(buffer_size, create_buffers, free_buffers, NULL),
1359 BENCH_INFO_COND(buffer_user_area, create_buffers, free_buffers, NULL, check_uarea),
1360 BENCH_INFO(buffer_pool, create_buffers, free_buffers, NULL),
1361 BENCH_INFO(buffer_alloc, NULL, free_buffers, NULL),
1362 BENCH_INFO(buffer_alloc_multi, NULL, free_buffers_multi, NULL),
1363 BENCH_INFO(buffer_free, create_buffers, NULL, NULL),
1364 BENCH_INFO(buffer_free_multi, create_buffers_multi, NULL, NULL),
1365 BENCH_INFO(buffer_alloc_free, NULL, NULL, NULL),
1366 BENCH_INFO(buffer_alloc_free_multi, NULL, NULL, NULL),
1367 BENCH_INFO(buffer_is_valid, create_buffers, free_buffers, NULL),
1368 BENCH_INFO(event_type, create_events, free_buffers, NULL),
1369 BENCH_INFO(event_subtype, create_events, free_buffers, NULL),
1370 BENCH_INFO(event_types, create_events, free_buffers, NULL),
1371 BENCH_INFO(event_types_multi, create_events_multi, free_buffers_multi, NULL),
1372 BENCH_INFO(event_types_multi_no_sub, create_events_multi, free_buffers_multi,
1373 "event_types_multi (no sub)"),
1374 BENCH_INFO(event_type_multi, create_events_multi, free_buffers_multi, NULL),
1375 BENCH_INFO(event_pool, create_events, free_buffers, NULL),
1376 BENCH_INFO_COND(event_user_area, create_events, free_buffers, NULL, check_uarea),
1377 BENCH_INFO_COND(event_user_area_and_flag, create_events, free_buffers, NULL, check_uarea),
1378 BENCH_INFO(event_is_valid, create_events, free_buffers, NULL),
1379 BENCH_INFO(event_free, create_events, NULL, NULL),
1380 BENCH_INFO(event_free_multi, create_events_multi, NULL, NULL),
1381 BENCH_INFO(event_free_sp, create_events_multi, NULL, NULL),
1382 BENCH_INFO_COND(event_flow_id, create_events, free_buffers, NULL, check_flow_aware),
1383 BENCH_INFO_COND(event_flow_id_set, create_events, free_buffers, NULL, check_flow_aware),
1384};
1385
1386ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite) < TEST_MAX_BENCH,
1387 "Result array is too small to hold all the results");
1388
1392bench_tm_info_t test_suite_tm[] = {
1393 BENCH_INFO_TM(buffer_from_event_tm, create_events, free_buffers, NULL),
1394 BENCH_INFO_TM(buffer_from_event_multi_tm, create_events_multi, free_buffers_multi, NULL),
1395 BENCH_INFO_TM(buffer_to_event_tm, create_buffers, free_buffers, NULL),
1396 BENCH_INFO_TM(buffer_to_event_multi_tm, create_buffers_multi, free_buffers_multi, NULL),
1397 BENCH_INFO_TM(buffer_addr_tm, create_buffers, free_buffers, NULL),
1398 BENCH_INFO_TM(buffer_size_tm, create_buffers, free_buffers, NULL),
1399 BENCH_INFO_TM(buffer_user_area_tm, create_buffers, free_buffers, check_uarea),
1400 BENCH_INFO_TM(buffer_pool_tm, create_buffers, free_buffers, NULL),
1401 BENCH_INFO_TM(buffer_alloc_tm, NULL, free_buffers, NULL),
1402 BENCH_INFO_TM(buffer_alloc_multi_tm, NULL, free_buffers_multi, NULL),
1403 BENCH_INFO_TM(buffer_free_tm, create_buffers, NULL, NULL),
1404 BENCH_INFO_TM(buffer_free_multi_tm, create_buffers_multi, NULL, NULL),
1405 BENCH_INFO_TM(buffer_alloc_free_tm, NULL, NULL, NULL),
1406 BENCH_INFO_TM(buffer_alloc_free_multi_tm, NULL, NULL, NULL),
1407 BENCH_INFO_TM(buffer_is_valid_tm, create_buffers, free_buffers, NULL),
1408 BENCH_INFO_TM(event_type_tm, create_events, free_buffers, NULL),
1409 BENCH_INFO_TM(event_subtype_tm, create_events, free_buffers, NULL),
1410 BENCH_INFO_TM(event_types_tm, create_events, free_buffers, NULL),
1411 BENCH_INFO_TM(event_types_multi_tm, create_events_multi, free_buffers_multi, NULL),
1412 BENCH_INFO_TM(event_types_multi_no_sub_tm, create_events_multi, free_buffers_multi, NULL),
1413 BENCH_INFO_TM(event_type_multi_tm, create_events_multi, free_buffers_multi, NULL),
1414 BENCH_INFO_TM(event_pool_tm, create_events, free_buffers, NULL),
1415 BENCH_INFO_TM(event_user_area_tm, create_events, free_buffers, check_uarea),
1416 BENCH_INFO_TM(event_user_area_and_flag_tm, create_events, free_buffers, check_uarea),
1417 BENCH_INFO_TM(event_is_valid_tm, create_events, free_buffers, NULL),
1418 BENCH_INFO_TM(event_free_tm, create_events, NULL, NULL),
1419 BENCH_INFO_TM(event_free_multi_tm, create_events_multi, NULL, NULL),
1420 BENCH_INFO_TM(event_free_sp_tm, create_events_multi, NULL, NULL),
1421 BENCH_INFO_TM(event_flow_id_tm, create_events, free_buffers, check_flow_aware),
1422 BENCH_INFO_TM(event_flow_id_set_tm, create_events, free_buffers, check_flow_aware),
1423};
1424
1425ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite_tm) < TEST_MAX_BENCH,
1426 "Result array is too small to hold all the results");
1427
1428static void init_suite(args_t *gbl_args, odp_bool_t is_export)
1429{
1430 if (gbl_args->appl.mode == M_LATENCY) {
1431 bench_tm_suite_init(&gbl_args->suite.t);
1432 gbl_args->suite.t.bench = test_suite_tm;
1433 gbl_args->suite.t.num_bench = ODPH_ARRAY_SIZE(test_suite_tm);
1434 gbl_args->suite.t.rounds = TEST_REPEAT_COUNT;
1435 gbl_args->suite.t.bench_idx = gbl_args->appl.bench_idx;
1436 gbl_args->suite.t.measure_time = !!gbl_args->appl.time;
1437 gbl_args->suite.exit = &gbl_args->suite.t.exit_worker;
1438 gbl_args->suite.retval = &gbl_args->suite.t.retval;
1439 gbl_args->suite.args = &gbl_args->suite.t;
1440 gbl_args->suite.suite_fn = bench_tm_run;
1441 gbl_args->suite.export_fn = bench_buffer_tm_export;
1442
1443 if (is_export)
1444 gbl_args->suite.t.result = gbl_args->result.t;
1445 } else {
1446 bench_suite_init(&gbl_args->suite.b);
1447 gbl_args->suite.b.bench = test_suite;
1448 gbl_args->suite.b.num_bench = ODPH_ARRAY_SIZE(test_suite);
1449 gbl_args->suite.b.indef_idx = gbl_args->appl.bench_idx;
1450 gbl_args->suite.b.rounds = gbl_args->appl.rounds;
1451 gbl_args->suite.b.repeat_count = TEST_REPEAT_COUNT;
1452 gbl_args->suite.b.measure_time = !!gbl_args->appl.time;
1453 gbl_args->suite.exit = &gbl_args->suite.b.exit_worker;
1454 gbl_args->suite.retval = &gbl_args->suite.b.retval;
1455 gbl_args->suite.args = &gbl_args->suite.b;
1456 gbl_args->suite.suite_fn = bench_run;
1457 gbl_args->suite.export_fn = bench_buffer_export;
1458
1459 if (is_export)
1460 gbl_args->suite.b.result = gbl_args->result.b;
1461 }
1462}
1463
1467int main(int argc, char *argv[])
1468{
1469 odph_helper_options_t helper_options;
1470 test_common_options_t common_options;
1471 odph_thread_t worker_thread;
1472 odph_thread_common_param_t thr_common;
1473 odph_thread_param_t thr_param;
1474 int cpu;
1475 odp_shm_t shm;
1476 odp_cpumask_t cpumask, default_mask;
1477 odp_schedule_capability_t sched_capa;
1479 odp_pool_param_t params;
1480 odp_instance_t instance;
1481 odp_init_t init_param;
1482 uint32_t buf_num;
1483 uint8_t ret;
1484
1485 /* Let helper collect its own arguments (e.g. --odph_proc) */
1486 argc = odph_parse_options(argc, argv);
1487 if (odph_options(&helper_options)) {
1488 ODPH_ERR("Error: reading ODP helper options failed\n");
1489 exit(EXIT_FAILURE);
1490 }
1491
1492 argc = test_common_parse_options(argc, argv);
1493 if (test_common_options(&common_options)) {
1494 ODPH_ERR("Error: reading test options failed\n");
1495 exit(EXIT_FAILURE);
1496 }
1497
1498 odp_init_param_init(&init_param);
1499 init_param.mem_model = helper_options.mem_model;
1500
1501 /* Init ODP before calling anything else */
1502 if (odp_init_global(&instance, &init_param, NULL)) {
1503 ODPH_ERR("Error: ODP global init failed\n");
1504 exit(EXIT_FAILURE);
1505 }
1506
1507 /* Init this thread */
1508 if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
1509 ODPH_ERR("Error: ODP local init failed\n");
1510 exit(EXIT_FAILURE);
1511 }
1512
1513 /* Reserve memory for args from shared mem */
1514 shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0);
1515 if (shm == ODP_SHM_INVALID) {
1516 ODPH_ERR("Error: shared mem reserve failed\n");
1517 exit(EXIT_FAILURE);
1518 }
1519
1520 gbl_args = odp_shm_addr(shm);
1521 if (gbl_args == NULL) {
1522 ODPH_ERR("Error: shared mem alloc failed\n");
1523 exit(EXIT_FAILURE);
1524 }
1525
1526 memset(gbl_args, 0, sizeof(args_t));
1527
1528 /* Parse and store the application arguments */
1529 parse_args(argc, argv, &gbl_args->appl);
1530 init_suite(gbl_args, common_options.is_export);
1531
1532 /* Get default worker cpumask */
1533 if (odp_cpumask_default_worker(&default_mask, 1) != 1) {
1534 ODPH_ERR("Error: unable to allocate worker thread\n");
1535 exit(EXIT_FAILURE);
1536 }
1537 (void)odp_cpumask_to_str(&default_mask, gbl_args->cpumask_str,
1538 sizeof(gbl_args->cpumask_str));
1539
1540 if (odp_schedule_capability(&sched_capa)) {
1541 ODPH_ERR("Error: schedule capability failed\n");
1542 exit(EXIT_FAILURE);
1543 }
1544
1545 gbl_args->max_flow_id = 0;
1546 if (sched_capa.max_flow_id) {
1547 odp_schedule_config_t sched_config;
1548
1549 odp_schedule_config_init(&sched_config);
1550 sched_config.max_flow_id = 1;
1551
1552 if (odp_schedule_config(&sched_config)) {
1553 ODPH_ERR("Error: schedule config failed\n");
1554 exit(EXIT_FAILURE);
1555 }
1556 gbl_args->max_flow_id = 1;
1557 }
1558
1559 if (odp_pool_capability(&capa)) {
1560 ODPH_ERR("Error: unable to query pool capability\n");
1561 exit(EXIT_FAILURE);
1562 }
1563
1564 buf_num = gbl_args->appl.burst_size * TEST_REPEAT_COUNT;
1565
1566 if (capa.buf.max_num && capa.buf.max_num < buf_num) {
1567 ODPH_ERR("Error: pool size not supported (max %" PRIu32 ")\n", capa.buf.max_num);
1568 exit(EXIT_FAILURE);
1569 } else if (gbl_args->appl.cache_size > (int)capa.buf.max_cache_size) {
1570 ODPH_ERR("Error: cache size not supported (max %" PRIu32 ")\n",
1571 capa.buf.max_cache_size);
1572 exit(EXIT_FAILURE);
1573 }
1574
1575 gbl_args->buf_size = TEST_BUF_SIZE;
1576 if (capa.buf.max_size && capa.buf.max_size < TEST_BUF_SIZE)
1577 gbl_args->buf_size = capa.buf.max_size;
1578
1579 gbl_args->uarea_size = TEST_UAREA_SIZE < capa.buf.max_uarea_size ?
1580 TEST_UAREA_SIZE : capa.buf.max_uarea_size;
1581
1582 print_info();
1583
1584 /* Create buffer pool */
1585 odp_pool_param_init(&params);
1586 params.buf.size = gbl_args->buf_size;
1587 params.buf.num = buf_num;
1588 params.buf.uarea_size = gbl_args->uarea_size;
1589 if (gbl_args->appl.cache_size >= 0)
1590 params.buf.cache_size = gbl_args->appl.cache_size;
1591 params.type = ODP_POOL_BUFFER;
1592
1593 gbl_args->pool = odp_pool_create("microbench", &params);
1594 if (gbl_args->pool == ODP_POOL_INVALID) {
1595 ODPH_ERR("Error: pool create failed\n");
1596 exit(EXIT_FAILURE);
1597 }
1598
1599 odp_pool_print(gbl_args->pool);
1600
1601 memset(&worker_thread, 0, sizeof(odph_thread_t));
1602
1603 signal(SIGINT, sig_handler);
1604
1605 /* Create worker thread */
1606 cpu = odp_cpumask_first(&default_mask);
1607
1608 odp_cpumask_zero(&cpumask);
1609 odp_cpumask_set(&cpumask, cpu);
1610
1611 odph_thread_common_param_init(&thr_common);
1612 thr_common.instance = instance;
1613 thr_common.cpumask = &cpumask;
1614 thr_common.share_param = 1;
1615
1616 odph_thread_param_init(&thr_param);
1617 thr_param.start = gbl_args->suite.suite_fn;
1618 thr_param.arg = gbl_args->suite.args;
1619 thr_param.thr_type = ODP_THREAD_WORKER;
1620
1621 odph_thread_create(&worker_thread, &thr_common, &thr_param, 1);
1622
1623 odph_thread_join(&worker_thread, 1);
1624
1625 ret = *gbl_args->suite.retval;
1626
1627 if (ret == 0 && common_options.is_export) {
1628 if (gbl_args->suite.export_fn(gbl_args)) {
1629 ODPH_ERR("Error: Export failed\n");
1630 ret = -1;
1631 }
1632 }
1633
1634 if (odp_pool_destroy(gbl_args->pool)) {
1635 ODPH_ERR("Error: pool destroy\n");
1636 exit(EXIT_FAILURE);
1637 }
1638
1639 if (odp_shm_free(shm)) {
1640 ODPH_ERR("Error: shm free\n");
1641 exit(EXIT_FAILURE);
1642 }
1643
1644 if (odp_term_local()) {
1645 ODPH_ERR("Error: term local\n");
1646 exit(EXIT_FAILURE);
1647 }
1648
1649 if (odp_term_global(instance)) {
1650 ODPH_ERR("Error: term global\n");
1651 exit(EXIT_FAILURE);
1652 }
1653
1654 return ret;
1655}
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
uint32_t odp_buffer_size(odp_buffer_t buf)
Buffer maximum data size.
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.
void odp_buffer_free(odp_buffer_t buf)
Buffer free.
int odp_buffer_is_valid(odp_buffer_t buf)
Check that buffer is valid.
odp_buffer_t odp_buffer_from_event(odp_event_t ev)
Get buffer handle from event.
void * odp_buffer_user_area(odp_buffer_t buf)
Buffer user area.
void * odp_buffer_addr(odp_buffer_t buf)
Buffer start address.
int odp_buffer_alloc_multi(odp_pool_t pool, odp_buffer_t buf[], int num)
Allocate multiple buffers.
#define ODP_BUFFER_INVALID
Invalid buffer.
void odp_buffer_free_multi(const odp_buffer_t buf[], int num)
Free multiple buffers.
void odp_buffer_from_event_multi(odp_buffer_t buf[], const odp_event_t ev[], int num)
Convert multiple buffer events to buffer handles.
void odp_buffer_to_event_multi(const odp_buffer_t buf[], odp_event_t ev[], int num)
Convert multiple buffer handles to events.
odp_pool_t odp_buffer_pool(odp_buffer_t buf)
Buffer pool of the buffer.
#define odp_unlikely(x)
Branch unlikely taken.
Definition spec/hints.h:64
#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_sp(const odp_event_t event[], int num)
Free multiple events to the same pool.
void odp_event_free_multi(const odp_event_t event[], int num)
Free multiple events.
odp_event_subtype_t odp_event_subtype(odp_event_t event)
Event subtype of an event.
void odp_event_free(odp_event_t event)
Free event.
odp_pool_t odp_event_pool(odp_event_t event)
Event pool.
void odp_event_types_multi(const odp_event_t event[], odp_event_type_t type[], odp_event_subtype_t subtype[], int num)
Event types and subtypes of multiple events.
int odp_event_type_multi(const odp_event_t event[], int num, odp_event_type_t *type)
Event type of multiple events.
odp_event_type_t odp_event_type(odp_event_t event)
Event type of an event.
void * odp_event_user_area(odp_event_t event)
Event user area.
odp_event_subtype_t
Event subtype.
void * odp_event_user_area_and_flag(odp_event_t event, int *flag)
Event user area and flag.
odp_event_type_t
Event type.
void odp_event_flow_id_set(odp_event_t event, uint32_t flow_id)
Set event flow id value.
uint32_t odp_event_flow_id(odp_event_t event)
Event flow id value.
odp_event_type_t odp_event_types(odp_event_t event, odp_event_subtype_t *subtype)
Event type and subtype of an event.
int odp_event_is_valid(odp_event_t event)
Check that event is valid.
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()
void odp_pool_print(odp_pool_t pool)
Print pool info.
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_BUFFER
Buffer pool.
void odp_schedule_config_init(odp_schedule_config_t *config)
Initialize schedule configuration options.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
int odp_schedule_capability(odp_schedule_capability_t *capa)
Query scheduler capabilities.
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.
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_uarea_size
Maximum user area size in bytes.
uint32_t max_size
Maximum buffer data size in bytes.
uint32_t max_cache_size
Maximum size of thread local cache.
uint32_t uarea_size
Minimum user area size in bytes.
uint32_t num
Number of buffers in the pool.
uint32_t cache_size
Maximum number of buffers cached locally per thread.
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.
uint32_t max_flow_id
Maximum flow ID per queue.
Schedule configuration.
uint32_t max_flow_id
Maximum flow ID per queue.