API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_bench_event_vector.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2025 Nokia
3 */
4
13#ifndef _GNU_SOURCE
14#define _GNU_SOURCE /* Needed for sigaction */
15#endif
16
17#include <odp_api.h>
18#include <odp/helper/odph_api.h>
19
20#include <bench_common.h>
21#include <export_results.h>
22
23#include <getopt.h>
24#include <inttypes.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <signal.h>
28
30#define TEST_MAX_EVV_SIZE 128u
31
33#define TEST_EVV_SIZE 8
34
36#define TEST_BUF_SIZE 32
37
39#define TEST_UAREA_SIZE 8u
40
42#define TEST_REPEAT_COUNT 1000
43
45#define TEST_ROUNDS 100u
46
48#define TEST_MAX_BENCH 20
49
50#define BENCH_INFO(run_fn, init_fn, term_fn, alt_name) \
51 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .desc = alt_name}
52
56typedef struct {
57 int bench_idx;
58 int cache_size;
59 int time;
60 uint32_t rounds;
61 uint32_t max_evv_size;
62 uint32_t num_events;
63} appl_args_t;
64
68typedef struct {
70 appl_args_t appl;
72 bench_suite_t suite;
74 odp_pool_t evv_pool;
76 odp_pool_t buf_pool;
78 uint32_t evv_uarea_size;
80 odp_event_vector_t evv_arr[TEST_REPEAT_COUNT];
82 odp_event_t event_arr[TEST_REPEAT_COUNT];
84 odp_event_t buf_event_tbl[TEST_REPEAT_COUNT][TEST_MAX_EVV_SIZE];
86 void *ptr_tbl[TEST_REPEAT_COUNT];
88 odp_pool_t pool_tbl[TEST_REPEAT_COUNT];
90 odp_event_type_t event_type_arr[TEST_REPEAT_COUNT];
92 char cpumask_str[ODP_CPUMASK_STR_SIZE];
94 double result[TEST_MAX_BENCH];
95} args_t;
96
97/* Global pointer to args */
98static args_t *gbl_args;
99
100static void sig_handler(int signo ODP_UNUSED)
101{
102 if (gbl_args == NULL)
103 return;
104 odp_atomic_store_u32(&gbl_args->suite.exit_worker, 1);
105}
106
107static int setup_sig_handler(void)
108{
109 struct sigaction action = { .sa_handler = sig_handler };
110
111 if (sigemptyset(&action.sa_mask) || sigaction(SIGINT, &action, NULL))
112 return -1;
113
114 return 0;
115}
116
117static void allocate_test_evv_and_contents(odp_event_vector_t evv[], uint32_t num)
118{
119 odp_pool_t evv_pool = gbl_args->evv_pool;
120 odp_pool_t buf_pool = gbl_args->buf_pool;
121 uint32_t max_evv_size = gbl_args->appl.max_evv_size;
122 uint32_t num_events = gbl_args->appl.num_events;
123 odp_event_t (*buf_event_tbl)[TEST_MAX_EVV_SIZE] = gbl_args->buf_event_tbl;
124 odp_buffer_t buf[max_evv_size];
125 odp_event_t *evv_tbl;
126 uint32_t num_buf, i, j;
127 int alloc_ret;
128
129 for (i = 0; i < num; i++) {
130 evv[i] = odp_event_vector_alloc(evv_pool);
131 if (evv[i] == ODP_EVENT_VECTOR_INVALID)
132 ODPH_ABORT("Allocating test event vector failed\n");
133
134 odp_event_vector_tbl(evv[i], &evv_tbl);
135
136 num_buf = 0;
137 while (num_buf < num_events) {
138 alloc_ret = odp_buffer_alloc_multi(buf_pool,
139 &buf[num_buf], num_events - num_buf);
140 if (alloc_ret < 0)
141 ODPH_ABORT("Allocating test buffer(s) failed\n");
142 num_buf += alloc_ret;
143 }
144
145 for (j = 0; j < num_events; j++) {
146 buf_event_tbl[i][j] = odp_buffer_to_event(buf[j]);
147 evv_tbl[j] = buf_event_tbl[i][j];
148 }
149
150 odp_event_vector_size_set(evv[i], num_events);
151 }
152}
153
154static void create_event_vectors(void)
155{
156 odp_event_vector_t *evv = gbl_args->evv_arr;
157
158 allocate_test_evv_and_contents(evv, TEST_REPEAT_COUNT);
159}
160
161static void create_events(void)
162{
163 odp_event_vector_t *evv = gbl_args->evv_arr;
164 odp_event_t *tbl = gbl_args->event_arr;
165
166 allocate_test_evv_and_contents(evv, TEST_REPEAT_COUNT);
167 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
168 tbl[i] = odp_event_vector_to_event(evv[i]);
169}
170
175static void free_event_vector_size_set(void)
176{
177 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
178 uint32_t num_events = gbl_args->appl.num_events;
179
180 for (int i = 0; i < TEST_REPEAT_COUNT; i++) {
181 if (evv_arr[i] == ODP_EVENT_VECTOR_INVALID)
182 ODPH_ABORT("Freeing event vector failed\n");
183 odp_event_vector_size_set(evv_arr[i], num_events);
185 }
186}
187
188static void free_event_vectors(void)
189{
190 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
191
192 for (int i = 0; i < TEST_REPEAT_COUNT; i++) {
193 if (evv_arr[i] == ODP_EVENT_VECTOR_INVALID)
194 ODPH_ABORT("Freeing event vector failed\n");
196 }
197}
198
199static void free_buf_events(void)
200{
201 uint32_t num_events = gbl_args->appl.num_events;
202 odp_event_t (*buf_event_tbl)[TEST_MAX_EVV_SIZE] = gbl_args->buf_event_tbl;
203
204 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
205 odp_event_free_multi(buf_event_tbl[i], num_events);
206}
207
208static int event_vector_from_event(void)
209{
210 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
211 odp_event_t *event_arr = gbl_args->event_arr;
212 int i;
213
214 for (i = 0; i < TEST_REPEAT_COUNT; i++)
215 evv_arr[i] = odp_event_vector_from_event(event_arr[i]);
216
217 return i;
218}
219
220static int event_vector_to_event(void)
221{
222 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
223 odp_event_t *event_arr = gbl_args->event_arr;
224 int i;
225
226 for (i = 0; i < TEST_REPEAT_COUNT; i++)
227 event_arr[i] = odp_event_vector_to_event(evv_arr[i]);
228
229 return i;
230}
231
232static int event_vector_alloc(void)
233{
234 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
235 odp_pool_t evv_pool = gbl_args->evv_pool;
236 int i;
237
238 for (i = 0; i < TEST_REPEAT_COUNT; i++)
239 evv_arr[i] = odp_event_vector_alloc(evv_pool);
240
241 return i;
242}
243
244static int event_vector_free(void)
245{
246 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
247 int i;
248
249 for (i = 0; i < TEST_REPEAT_COUNT; i++)
250 odp_event_vector_free(evv_arr[i]);
251
252 return i;
253}
254
255static int event_free(void)
256{
257 odp_event_t *event_arr = gbl_args->event_arr;
258 int i;
259
260 for (i = 0; i < TEST_REPEAT_COUNT; i++)
261 odp_event_free(event_arr[i]);
262
263 return i;
264}
265
266static int event_vector_alloc_free(void)
267{
268 odp_pool_t evv_pool = gbl_args->evv_pool;
269 int i;
270
271 for (i = 0; i < TEST_REPEAT_COUNT; i++) {
273
275 return 0;
276
278 }
279 return i;
280}
281
282static int event_vector_tbl(void)
283{
284 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
285 uint32_t num_events = gbl_args->appl.num_events;
286 uint32_t ret = 0;
287 odp_event_t *ptr;
288
289 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
290 ret += odp_event_vector_tbl(evv_arr[i], &ptr);
291
292 return ret == num_events * TEST_REPEAT_COUNT;
293}
294
295static int event_vector_size(void)
296{
297 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
298 uint32_t num_events = gbl_args->appl.num_events;
299 uint32_t ret = 0;
300
301 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
302 ret += odp_event_vector_size(evv_arr[i]);
303
304 return ret == num_events * TEST_REPEAT_COUNT;
305}
306
307static int event_vector_type(void)
308{
309 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
310 odp_event_type_t *event_type = gbl_args->event_type_arr;
311 int i;
312
313 for (i = 0; i < TEST_REPEAT_COUNT; i++)
314 event_type[i] = odp_event_vector_type(evv_arr[i]);
315
316 return i;
317}
318
319static int event_vector_size_set(void)
320{
321 const uint32_t size = gbl_args->appl.num_events ? gbl_args->appl.num_events - 1 : 0;
322 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
323 int i;
324
325 for (i = 0; i < TEST_REPEAT_COUNT; i++)
326 odp_event_vector_size_set(evv_arr[i], size);
327
328 return i;
329}
330
331static int event_vector_user_area(void)
332{
333 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
334 void **ptr_tbl = gbl_args->ptr_tbl;
335 int i;
336
337 for (i = 0; i < TEST_REPEAT_COUNT; i++)
338 ptr_tbl[i] = odp_event_vector_user_area(evv_arr[i]);
339
340 return i;
341}
342
343static int event_vector_user_flag(void)
344{
345 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
346 int ret = 0;
347
348 for (int i = 0; i < TEST_REPEAT_COUNT; i++)
349 ret += !odp_event_vector_user_flag(evv_arr[i]);
350
351 return ret;
352}
353
354static int event_vector_user_flag_set(void)
355{
356 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
357 int i;
358
359 for (i = 0; i < TEST_REPEAT_COUNT; i++)
360 odp_event_vector_user_flag_set(evv_arr[i], 1);
361
362 return i;
363}
364
365static int event_vector_pool(void)
366{
367 odp_event_vector_t *evv_arr = gbl_args->evv_arr;
368 odp_pool_t *pool_tbl = gbl_args->pool_tbl;
369 int i;
370
371 for (i = 0; i < TEST_REPEAT_COUNT; i++)
372 pool_tbl[i] = odp_event_vector_pool(evv_arr[i]);
373
374 return i;
375}
376
380static void usage(void)
381{
382 printf("\n"
383 "OpenDataPlane Event vector API microbenchmarks.\n"
384 "\n"
385 "Optional OPTIONS:\n"
386 " -c, --cache_size <num> Pool cache size.\n"
387 " -i, --index <idx> Benchmark index to run indefinitely.\n"
388 " -r, --rounds <num> Run each test case 'num' times (default %u).\n"
389 " -m, -max_events <num> Maximum number of events in each event vector (default %u).\n"
390 " -n, --num_events <num> Number of events in each event vector (default %u).\n"
391 " -t, --time <opt> Time measurement. 0: measure CPU cycles (default), 1: measure time\n"
392 " -h, --help Display help and exit.\n\n"
393 "\n", TEST_ROUNDS, TEST_EVV_SIZE, TEST_EVV_SIZE);
394}
395
403static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
404{
405 int opt;
406 static const struct option longopts[] = {
407 {"cache_size", required_argument, NULL, 'c'},
408 {"index", required_argument, NULL, 'i'},
409 {"rounds", required_argument, NULL, 'r'},
410 {"max_events", required_argument, NULL, 'm'},
411 {"num_events", required_argument, NULL, 'n'},
412 {"time", required_argument, NULL, 't'},
413 {"help", no_argument, NULL, 'h'},
414 {NULL, 0, NULL, 0}
415 };
416
417 static const char *shortopts = "c:i:r:m:n:t:h";
418
419 appl_args->bench_idx = 0; /* Run all benchmarks */
420 appl_args->cache_size = -1;
421 appl_args->rounds = TEST_ROUNDS;
422 appl_args->max_evv_size = TEST_EVV_SIZE;
423 appl_args->num_events = TEST_EVV_SIZE;
424 appl_args->time = 0;
425
426 while (1) {
427 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
428
429 if (opt == -1)
430 break; /* No more options */
431
432 switch (opt) {
433 case 'c':
434 appl_args->cache_size = atoi(optarg);
435 break;
436 case 'h':
437 usage();
438 exit(EXIT_SUCCESS);
439 break;
440 case 'i':
441 appl_args->bench_idx = atoi(optarg);
442 break;
443 case 'r':
444 appl_args->rounds = atoi(optarg);
445 break;
446 case 'm':
447 appl_args->max_evv_size = atoi(optarg);
448 break;
449 case 'n':
450 appl_args->num_events = atoi(optarg);
451 break;
452 case 't':
453 appl_args->time = atoi(optarg);
454 break;
455 default:
456 break;
457 }
458 }
459
460 if (appl_args->rounds < 1) {
461 printf("Invalid number test rounds: %d\n", appl_args->rounds);
462 exit(EXIT_FAILURE);
463 }
464
465 if (appl_args->max_evv_size == 0) {
466 printf("Invalid event vector maximum size: %d\n", appl_args->max_evv_size);
467 exit(EXIT_FAILURE);
468 }
469
470 optind = 1; /* Reset 'extern optind' from the getopt lib */
471}
472
476static void print_info(void)
477{
479
480 printf("\n"
481 "odp_bench_event_vector options\n"
482 "------------------------\n");
483
484 printf("Maximum number of events in each event vector: %d\n",
485 gbl_args->appl.max_evv_size);
486 printf("Number of events in each event vector: %d\n",
487 gbl_args->appl.num_events);
488 printf("CPU mask: %s\n",
489 gbl_args->cpumask_str);
490 if (gbl_args->appl.cache_size < 0)
491 printf("Pool cache size: default\n");
492 else
493 printf("Pool cache size: %d\n",
494 gbl_args->appl.cache_size);
495 printf("Measurement unit: %s\n",
496 gbl_args->appl.time ? "nsec" : "CPU cycles");
497 printf("Test rounds: %u\n",
498 gbl_args->appl.rounds);
499 printf("\n");
500}
501
502static int bench_event_vector_export(void *data)
503{
504 args_t *gbl_args = data;
505 int ret = 0;
506
507 if (test_common_write("%s", gbl_args->appl.time ?
508 "function name,average nsec per function call\n" :
509 "function name,average cpu cycles per function call\n")) {
510 ret = -1;
511 goto exit;
512 }
513
514 for (int i = 0; i < gbl_args->suite.num_bench; i++) {
515 if (test_common_write("odp_%s,%f\n", gbl_args->suite.bench[i].desc != NULL ?
516 gbl_args->suite.bench[i].desc : gbl_args->suite.bench[i].name,
517 gbl_args->suite.result[i])) {
518 ret = -1;
519 goto exit;
520 }
521 }
522
523exit:
524 test_common_write_term();
525
526 return ret;
527}
528
532bench_info_t test_suite[] = {
533 BENCH_INFO(event_vector_from_event, create_events, free_event_vectors, NULL),
534 BENCH_INFO(event_vector_to_event, create_event_vectors, free_event_vectors, NULL),
535 BENCH_INFO(event_vector_alloc, NULL, free_event_vectors, NULL),
536 BENCH_INFO(event_vector_free, create_event_vectors, free_buf_events, NULL),
537 BENCH_INFO(event_free, create_events, NULL, NULL),
538 BENCH_INFO(event_vector_alloc_free, NULL, NULL, NULL),
539 BENCH_INFO(event_vector_tbl, create_event_vectors, free_event_vectors, NULL),
540 BENCH_INFO(event_vector_size, create_event_vectors, free_event_vectors, NULL),
541 BENCH_INFO(event_vector_type, create_event_vectors, free_event_vectors, NULL),
542 BENCH_INFO(event_vector_size_set, create_event_vectors, free_event_vector_size_set, NULL),
543 BENCH_INFO(event_vector_user_area, create_event_vectors, free_event_vectors, NULL),
544 BENCH_INFO(event_vector_user_flag, create_event_vectors, free_event_vectors, NULL),
545 BENCH_INFO(event_vector_user_flag_set, create_event_vectors, free_event_vectors, NULL),
546 BENCH_INFO(event_vector_pool, create_event_vectors, free_event_vectors, NULL),
547};
548
549ODP_STATIC_ASSERT(ODPH_ARRAY_SIZE(test_suite) < TEST_MAX_BENCH,
550 "Result array is too small to hold all the results");
551
552static int create_pools(void)
553{
555 odp_pool_param_t evv_pool_params;
556 odp_pool_param_t buf_pool_params;
557 uint32_t buf_num = TEST_REPEAT_COUNT * gbl_args->appl.num_events;
558
559 if (odp_pool_capability(&capa)) {
560 ODPH_ERR("Error: unable to query pool capability\n");
561 return -1;
562 }
563
564 if (capa.event_vector.max_pools == 0) {
565 ODPH_ERR("Error: event vector pools not supported\n");
566 return -1;
567 }
568
569 if (capa.event_vector.max_num && capa.event_vector.max_num < TEST_REPEAT_COUNT) {
570 ODPH_ERR("Error: event vector pool size not supported (max %" PRIu32 ")\n",
571 capa.event_vector.max_num);
572 return -1;
573 }
574
575 if (gbl_args->appl.cache_size > (int)capa.event_vector.max_cache_size) {
576 ODPH_ERR("Error: cache size not supported (max %" PRIu32 ")\n",
578 return -1;
579 }
580
581 if (gbl_args->appl.cache_size != -1 &&
582 gbl_args->appl.cache_size < (int)capa.buf.min_cache_size) {
583 ODPH_ERR("Error: event vector pool cache size not supported (min %" PRIu32 ")\n",
585 return -1;
586 }
587
588 if (gbl_args->appl.max_evv_size > ODPH_MIN(TEST_MAX_EVV_SIZE, capa.event_vector.max_size)) {
589 ODPH_ERR("Error: event vector size not supported (max %" PRIu32 ")\n",
590 ODPH_MIN(capa.event_vector.max_size, TEST_MAX_EVV_SIZE));
591 return -1;
592 }
593
594 if (gbl_args->appl.num_events > gbl_args->appl.max_evv_size) {
595 ODPH_ERR("Error: number of event vector elements is larger than max (%u/%u)\n",
596 gbl_args->appl.num_events, gbl_args->appl.max_evv_size);
597 return -1;
598 }
599
600 gbl_args->evv_uarea_size = ODPH_MIN(TEST_UAREA_SIZE, capa.event_vector.max_uarea_size);
601
602 if (buf_num > capa.buf.max_num) {
603 ODPH_ERR("Error: buffer pool size not supported (max %" PRIu32 ")\n",
604 capa.buf.max_num);
605 return -1;
606 }
607
608 print_info();
609
610 /* Create event vector pool */
611 odp_pool_param_init(&evv_pool_params);
612 evv_pool_params.event_vector.max_size = gbl_args->appl.max_evv_size;
613 evv_pool_params.event_vector.num = TEST_REPEAT_COUNT;
614 evv_pool_params.event_vector.uarea_size = gbl_args->evv_uarea_size;
615
616 if (gbl_args->appl.cache_size >= 0)
617 evv_pool_params.event_vector.cache_size = gbl_args->appl.cache_size;
618
619 evv_pool_params.type = ODP_POOL_EVENT_VECTOR;
620 gbl_args->evv_pool = odp_pool_create("microbench event vector", &evv_pool_params);
621
622 if (gbl_args->evv_pool == ODP_POOL_INVALID) {
623 ODPH_ERR("Error: pool create failed\n");
624 return -1;
625 }
626
627 odp_pool_print(gbl_args->evv_pool);
628
629 /* Create buffer pool */
630 if (gbl_args->appl.num_events) {
631 odp_pool_param_init(&buf_pool_params);
632 buf_pool_params.buf.size = TEST_BUF_SIZE;
633 buf_pool_params.buf.num = buf_num;
634 buf_pool_params.type = ODP_POOL_BUFFER;
635
636 gbl_args->buf_pool = odp_pool_create("microbench buffer", &buf_pool_params);
637 if (gbl_args->buf_pool == ODP_POOL_INVALID) {
638 ODPH_ERR("Error: pool create failed\n");
639 return -1;
640 }
641
642 odp_pool_print(gbl_args->buf_pool);
643 }
644
645 return 0;
646}
647
651int main(int argc, char *argv[])
652{
653 odph_helper_options_t helper_options;
654 test_common_options_t common_options;
655 odph_thread_t worker_thread;
656 odph_thread_common_param_t thr_common;
657 odph_thread_param_t thr_param;
658 int cpu;
659 odp_shm_t shm;
660 odp_cpumask_t cpumask, default_mask;
661 odp_instance_t instance;
662 odp_init_t init_param;
663 uint8_t ret;
664
665 /* Let helper collect its own arguments (e.g. --odph_proc) */
666 argc = odph_parse_options(argc, argv);
667 if (odph_options(&helper_options)) {
668 ODPH_ERR("Error: reading ODP helper options failed\n");
669 exit(EXIT_FAILURE);
670 }
671
672 argc = test_common_parse_options(argc, argv);
673 if (test_common_options(&common_options)) {
674 ODPH_ERR("Error: reading test options failed\n");
675 exit(EXIT_FAILURE);
676 }
677
678 odp_init_param_init(&init_param);
679 init_param.mem_model = helper_options.mem_model;
680
681 if (setup_sig_handler()) {
682 ODPH_ERR("Signal handler setup failed\n");
683 exit(EXIT_FAILURE);
684 }
685
686 /* Init ODP before calling anything else */
687 if (odp_init_global(&instance, &init_param, NULL)) {
688 ODPH_ERR("Error: ODP global init failed\n");
689 exit(EXIT_FAILURE);
690 }
691
692 /* Init this thread */
693 if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
694 ODPH_ERR("Error: ODP local init failed\n");
695 exit(EXIT_FAILURE);
696 }
697
698 /* Reserve memory for args from shared mem */
699 shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0);
700 if (shm == ODP_SHM_INVALID) {
701 ODPH_ERR("Error: shared mem reserve failed\n");
702 exit(EXIT_FAILURE);
703 }
704
705 gbl_args = odp_shm_addr(shm);
706 if (gbl_args == NULL) {
707 ODPH_ERR("Error: shared mem alloc failed\n");
708 exit(EXIT_FAILURE);
709 }
710
711 memset(gbl_args, 0, sizeof(args_t));
712
713 /* Parse and store the application arguments */
714 parse_args(argc, argv, &gbl_args->appl);
715
716 bench_suite_init(&gbl_args->suite);
717 gbl_args->suite.bench = test_suite;
718 gbl_args->suite.num_bench = ODPH_ARRAY_SIZE(test_suite);
719 gbl_args->suite.indef_idx = gbl_args->appl.bench_idx;
720 gbl_args->suite.rounds = gbl_args->appl.rounds;
721 gbl_args->suite.repeat_count = TEST_REPEAT_COUNT;
722 gbl_args->suite.measure_time = !!gbl_args->appl.time;
723 if (common_options.is_export)
724 gbl_args->suite.result = gbl_args->result;
725
726 /* Get default worker cpumask */
727 if (odp_cpumask_default_worker(&default_mask, 1) != 1) {
728 ODPH_ERR("Error: unable to allocate worker thread\n");
729 ret = -1;
730 goto exit;
731 }
732 (void)odp_cpumask_to_str(&default_mask, gbl_args->cpumask_str,
733 sizeof(gbl_args->cpumask_str));
734
735 if (create_pools()) {
736 ret = -1;
737 goto exit;
738 }
739
740 /* Create worker thread */
741 cpu = odp_cpumask_first(&default_mask);
742
743 odp_cpumask_zero(&cpumask);
744 odp_cpumask_set(&cpumask, cpu);
745
746 odph_thread_common_param_init(&thr_common);
747 thr_common.instance = instance;
748 thr_common.cpumask = &cpumask;
749 thr_common.share_param = 1;
750
751 odph_thread_param_init(&thr_param);
752 thr_param.start = bench_run;
753 thr_param.arg = &gbl_args->suite;
754 thr_param.thr_type = ODP_THREAD_WORKER;
755
756 if (odph_thread_create(&worker_thread, &thr_common, &thr_param, 1) != 1) {
757 ODPH_ERR("Error: unable to create worker thread\n");
758 ret = -1;
759 goto exit;
760 }
761
762 if (odph_thread_join(&worker_thread, 1) != 1) {
763 ODPH_ERR("Error: unable to join worker thread\n");
764 ret = -1;
765 goto exit;
766 }
767
768 ret = gbl_args->suite.retval;
769
770 if (ret == 0 && common_options.is_export) {
771 if (bench_event_vector_export(gbl_args)) {
772 ODPH_ERR("Error: Export failed\n");
773 ret = -1;
774 }
775 }
776
777exit:
778 if ((gbl_args->evv_pool && odp_pool_destroy(gbl_args->evv_pool)) ||
779 (gbl_args->buf_pool && odp_pool_destroy(gbl_args->buf_pool))) {
780 ODPH_ERR("Error: pool destroy\n");
781 exit(EXIT_FAILURE);
782 }
783
784 if (odp_shm_free(shm)) {
785 ODPH_ERR("Error: shm free\n");
786 exit(EXIT_FAILURE);
787 }
788
789 if (odp_term_local()) {
790 ODPH_ERR("Error: term local\n");
791 exit(EXIT_FAILURE);
792 }
793
794 if (odp_term_global(instance)) {
795 ODPH_ERR("Error: term global\n");
796 exit(EXIT_FAILURE);
797 }
798
799 return ret;
800}
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.
int odp_buffer_alloc_multi(odp_pool_t pool, odp_buffer_t buf[], int num)
Allocate multiple buffers.
#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_...
odp_event_t odp_event_vector_to_event(odp_event_vector_t evv)
Convert event vector handle to event.
void odp_event_vector_size_set(odp_event_vector_t evv, uint32_t size)
Set the number of events stored in a vector.
void odp_event_vector_free(odp_event_vector_t evv)
Free event vector.
odp_event_vector_t odp_event_vector_from_event(odp_event_t ev)
Get event vector handle from event.
uint32_t odp_event_vector_tbl(odp_event_vector_t evv, odp_event_t **event_tbl)
Get event vector table.
int odp_event_vector_user_flag(odp_event_vector_t evv)
Check user flag.
odp_event_vector_t odp_event_vector_alloc(odp_pool_t pool)
Allocate event vector from event vector pool.
uint32_t odp_event_vector_size(odp_event_vector_t evv)
Number of events in a vector.
#define ODP_EVENT_VECTOR_INVALID
Invalid event vector.
odp_pool_t odp_event_vector_pool(odp_event_vector_t evv)
Event vector pool.
void odp_event_vector_user_flag_set(odp_event_vector_t evv, int val)
Set user flag.
void * odp_event_vector_user_area(odp_event_vector_t evv)
Event vector user area.
odp_event_type_t odp_event_vector_type(odp_event_vector_t evv)
Type of events stored in event vector.
void odp_event_free_multi(const odp_event_t event[], int num)
Free multiple events.
void odp_event_free(odp_event_t event)
Free event.
_odp_abi_event_t * odp_event_t
ODP event.
odp_event_type_t
Event type.
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.
@ ODP_POOL_EVENT_VECTOR
Event vector pool.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
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.
uint32_t min_cache_size
Minimum size of thread local cache.
struct odp_pool_capability_t::@133 buf
Buffer pool capabilities
uint32_t max_uarea_size
Maximum user area size in bytes.
struct odp_pool_capability_t::@137 event_vector
Event vector pool capabilities.
uint32_t max_size
Maximum buffer data size in bytes.
uint32_t max_cache_size
Maximum size of thread local cache.
uint32_t max_pools
Maximum number of pools of any type (odp_pool_type_t)
uint32_t uarea_size
Minimum user area size in bytes.
uint32_t num
Number of buffers in the pool.
struct odp_pool_param_t::@142 event_vector
Parameters for event vector pools.
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.
uint32_t max_size
Maximum number of handles (such as odp_packet_t) in a vector.
struct odp_pool_param_t::@138 buf
Parameters for buffer pools.