API Reference Manual  1.46.0
odp_pool_perf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2018 Linaro Limited
3  * Copyright (c) 2019-2024 Nokia
4  */
5 
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdint.h>
17 #include <inttypes.h>
18 #include <stdlib.h>
19 #include <getopt.h>
20 
21 #include <odp_api.h>
22 #include <odp/helper/odph_api.h>
23 
24 #include <export_results.h>
25 
26 #define STAT_AVAILABLE 0x1
27 #define STAT_CACHE 0x2
28 #define STAT_THR_CACHE 0x4
29 #define STAT_ALLOC_OPS 0x10
30 #define STAT_FREE_OPS 0x20
31 #define STAT_TOTAL_OPS 0x40
32 
33 typedef struct test_options_t {
34  uint32_t num_cpu;
35  uint32_t num_event;
36  uint32_t num_round;
37  uint32_t max_burst;
38  uint32_t num_burst;
39  uint32_t data_size;
40  uint32_t cache_size;
41  uint32_t stats_mode;
42  int pool_type;
43 
44 } test_options_t;
45 
46 typedef struct test_stat_t {
47  uint64_t rounds;
48  uint64_t frees;
49  uint64_t events;
50  uint64_t nsec;
51  uint64_t cycles;
52 
53 } test_stat_t;
54 
55 typedef struct test_global_t {
56  test_options_t test_options;
57 
58  odp_barrier_t barrier;
59  odp_pool_t pool;
60  odp_cpumask_t cpumask;
61  odph_thread_t thread_tbl[ODP_THREAD_COUNT_MAX];
62  test_stat_t stat[ODP_THREAD_COUNT_MAX];
63  test_common_options_t common_options;
64 
65 } test_global_t;
66 
67 static void print_usage(void)
68 {
69  printf("\n"
70  "Pool performance test\n"
71  "\n"
72  "Usage: odp_pool_perf [options]\n"
73  "\n"
74  " -c, --num_cpu Number of CPUs (worker threads). 0: all available CPUs. Default 1.\n"
75  " -e, --num_event Number of events\n"
76  " -r, --num_round Number of rounds\n"
77  " -b, --burst Maximum number of events per operation\n"
78  " -n, --num_burst Number of bursts allocated/freed back-to-back\n"
79  " -s, --data_size Data size in bytes\n"
80  " -S, --stats_mode Pool statistics usage. Enable counters with combination of these flags:\n"
81  " 0: no pool statistics (default)\n"
82  " 0x1: available\n"
83  " 0x2: cache_available\n"
84  " 0x4: thread_cache_available\n"
85  " 0x10: alloc_ops\n"
86  " 0x20: free_ops\n"
87  " 0x40: total_ops\n"
88  " -t, --pool_type 0: Buffer pool (default)\n"
89  " 1: Packet pool\n"
90  " -C, --cache_size Pool cache size (per thread)\n"
91  " -h, --help This help\n"
92  "\n");
93 }
94 
95 static int parse_options(int argc, char *argv[], test_options_t *test_options)
96 {
97  int opt;
98  int ret = 0;
99 
100  static const struct option longopts[] = {
101  {"num_cpu", required_argument, NULL, 'c'},
102  {"num_event", required_argument, NULL, 'e'},
103  {"num_round", required_argument, NULL, 'r'},
104  {"burst", required_argument, NULL, 'b'},
105  {"num_burst", required_argument, NULL, 'n'},
106  {"data_size", required_argument, NULL, 's'},
107  {"stats_mode", required_argument, NULL, 'S'},
108  {"pool_type", required_argument, NULL, 't'},
109  {"cache_size", required_argument, NULL, 'C'},
110  {"help", no_argument, NULL, 'h'},
111  {NULL, 0, NULL, 0}
112  };
113 
114  static const char *shortopts = "+c:e:r:b:n:s:S:t:C:h";
115 
116  test_options->num_cpu = 1;
117  test_options->num_event = 1000;
118  test_options->num_round = 100000;
119  test_options->max_burst = 100;
120  test_options->num_burst = 1;
121  test_options->data_size = 64;
122  test_options->stats_mode = 0;
123  test_options->pool_type = 0;
124  test_options->cache_size = UINT32_MAX;
125 
126  while (1) {
127  opt = getopt_long(argc, argv, shortopts, longopts, NULL);
128 
129  if (opt == -1)
130  break;
131 
132  switch (opt) {
133  case 'c':
134  test_options->num_cpu = atoi(optarg);
135  break;
136  case 'e':
137  test_options->num_event = atoi(optarg);
138  break;
139  case 'r':
140  test_options->num_round = atoi(optarg);
141  break;
142  case 'b':
143  test_options->max_burst = atoi(optarg);
144  break;
145  case 'n':
146  test_options->num_burst = atoi(optarg);
147  break;
148  case 's':
149  test_options->data_size = atoi(optarg);
150  break;
151  case 'S':
152  test_options->stats_mode = strtoul(optarg, NULL, 0);
153  break;
154  case 't':
155  test_options->pool_type = atoi(optarg);
156  break;
157  case 'C':
158  test_options->cache_size = atoi(optarg);
159  break;
160  case 'h':
161  /* fall through */
162  default:
163  print_usage();
164  ret = -1;
165  break;
166  }
167  }
168 
169  if (test_options->num_burst * test_options->max_burst >
170  test_options->num_event) {
171  printf("Not enough events (%u) for the burst configuration.\n"
172  "Use smaller burst size (%u) or less bursts (%u)\n",
173  test_options->num_event, test_options->max_burst,
174  test_options->num_burst);
175  ret = -1;
176  }
177 
178  return ret;
179 }
180 
181 static int set_num_cpu(test_global_t *global)
182 {
183  int ret;
184  test_options_t *test_options = &global->test_options;
185  int num_cpu = test_options->num_cpu;
186 
187  /* One thread used for the main thread */
188  if (num_cpu > ODP_THREAD_COUNT_MAX - 1) {
189  printf("Error: Too many workers. Maximum is %i.\n",
191  return -1;
192  }
193 
194  ret = odp_cpumask_default_worker(&global->cpumask, num_cpu);
195 
196  if (num_cpu && ret != num_cpu) {
197  printf("Error: Too many workers. Max supported %i.\n", ret);
198  return -1;
199  }
200 
201  /* Zero: all available workers */
202  if (num_cpu == 0) {
203  num_cpu = ret;
204  test_options->num_cpu = num_cpu;
205  }
206 
207  odp_barrier_init(&global->barrier, num_cpu);
208 
209  return 0;
210 }
211 
212 static int create_pool(test_global_t *global)
213 {
214  odp_pool_capability_t pool_capa;
215  odp_pool_param_t pool_param;
216  odp_pool_t pool;
217  odp_pool_stats_opt_t stats, stats_capa;
218  uint32_t max_num, max_size, min_cache_size, max_cache_size;
219  test_options_t *test_options = &global->test_options;
220  uint32_t num_event = test_options->num_event;
221  uint32_t num_round = test_options->num_round;
222  uint32_t max_burst = test_options->max_burst;
223  uint32_t num_burst = test_options->num_burst;
224  uint32_t num_cpu = test_options->num_cpu;
225  uint32_t data_size = test_options->data_size;
226  uint32_t cache_size = test_options->cache_size;
227  uint32_t stats_mode = test_options->stats_mode;
228  int packet_pool = test_options->pool_type;
229 
230  stats.all = 0;
231 
232  odp_pool_param_init(&pool_param);
233 
234  if (cache_size == UINT32_MAX)
235  cache_size = packet_pool ? pool_param.pkt.cache_size :
236  pool_param.buf.cache_size;
237 
238  if (stats_mode & STAT_AVAILABLE)
239  stats.bit.available = 1;
240  if (stats_mode & STAT_CACHE)
241  stats.bit.cache_available = 1;
242  if (stats_mode & STAT_THR_CACHE)
243  stats.bit.thread_cache_available = 1;
244  if (stats_mode & STAT_ALLOC_OPS)
245  stats.bit.alloc_ops = 1;
246  if (stats_mode & STAT_FREE_OPS)
247  stats.bit.free_ops = 1;
248  if (stats_mode & STAT_TOTAL_OPS)
249  stats.bit.total_ops = 1;
250 
251  printf("\nPool performance test\n");
252  printf(" num cpu %u\n", num_cpu);
253  printf(" num rounds %u\n", num_round);
254  printf(" num events %u\n", num_event);
255  printf(" max burst %u\n", max_burst);
256  printf(" num bursts %u\n", num_burst);
257  printf(" data size %u\n", data_size);
258  printf(" cache size %u\n", cache_size);
259  printf(" stats mode 0x%x\n", stats_mode);
260  printf(" pool type %s\n\n", packet_pool ? "packet" : "buffer");
261 
262  if (odp_pool_capability(&pool_capa)) {
263  printf("Error: Pool capa failed.\n");
264  return -1;
265  }
266 
267  if (packet_pool) {
268  max_num = pool_capa.pkt.max_num;
269  max_size = pool_capa.pkt.max_len;
270  max_cache_size = pool_capa.pkt.max_cache_size;
271  min_cache_size = pool_capa.pkt.min_cache_size;
272  stats_capa = pool_capa.pkt.stats;
273  } else {
274  max_num = pool_capa.buf.max_num;
275  max_size = pool_capa.buf.max_size;
276  max_cache_size = pool_capa.buf.max_cache_size;
277  min_cache_size = pool_capa.buf.min_cache_size;
278  stats_capa = pool_capa.buf.stats;
279  }
280 
281  if ((stats_capa.all & stats.all) != stats.all) {
282  printf("Error: requested statistics not supported (0x%" PRIx64 " / 0x%" PRIx64 ")\n",
283  stats.all, stats_capa.all);
284  return -1;
285  }
286 
287  if (cache_size < min_cache_size) {
288  printf("Error: min cache size supported %u\n", min_cache_size);
289  return -1;
290  }
291 
292  if (cache_size > max_cache_size) {
293  printf("Error: max cache size supported %u\n", max_cache_size);
294  return -1;
295  }
296 
297  if (max_num && num_event > max_num) {
298  printf("Error: max events supported %u\n", max_num);
299  return -1;
300  }
301 
302  if (max_size && data_size > max_size) {
303  printf("Error: max data size supported %u\n", max_size);
304  return -1;
305  }
306 
307  if (packet_pool) {
308  pool_param.type = ODP_POOL_PACKET;
309  pool_param.pkt.num = num_event;
310  pool_param.pkt.len = data_size;
311  pool_param.pkt.max_num = num_event;
312  pool_param.pkt.max_len = data_size;
313  pool_param.pkt.cache_size = cache_size;
314  } else {
315  pool_param.type = ODP_POOL_BUFFER;
316  pool_param.buf.num = num_event;
317  pool_param.buf.size = data_size;
318  pool_param.buf.cache_size = cache_size;
319  }
320 
321  pool_param.stats.all = stats.all;
322 
323  pool = odp_pool_create("pool perf", &pool_param);
324 
325  if (pool == ODP_POOL_INVALID) {
326  printf("Error: Pool create failed.\n");
327  return -1;
328  }
329 
330  global->pool = pool;
331 
332  return 0;
333 }
334 
335 static int test_buffer_pool(void *arg)
336 {
337  int ret, thr;
338  uint32_t num, num_free, num_freed, i, rounds;
339  uint64_t c1, c2, cycles, nsec;
340  uint64_t events, frees;
341  odp_time_t t1, t2;
342  test_global_t *global = arg;
343  test_options_t *test_options = &global->test_options;
344  uint32_t num_round = test_options->num_round;
345  uint32_t max_burst = test_options->max_burst;
346  uint32_t num_burst = test_options->num_burst;
347  uint32_t max_num = num_burst * max_burst;
348  odp_pool_t pool = global->pool;
349  odp_buffer_t buf[max_num];
350 
351  thr = odp_thread_id();
352 
353  for (i = 0; i < max_num; i++)
354  buf[i] = ODP_BUFFER_INVALID;
355 
356  events = 0;
357  frees = 0;
358  ret = 0;
359 
360  /* Start all workers at the same time */
361  odp_barrier_wait(&global->barrier);
362 
363  t1 = odp_time_local();
364  c1 = odp_cpu_cycles();
365 
366  for (rounds = 0; rounds < num_round; rounds++) {
367  num = 0;
368 
369  for (i = 0; i < num_burst; i++) {
370  ret = odp_buffer_alloc_multi(pool, &buf[num],
371  max_burst);
372  if (odp_unlikely(ret < 0)) {
373  printf("Error: Alloc failed. Round %u\n",
374  rounds);
375  if (num)
376  odp_buffer_free_multi(buf, num);
377 
378  return -1;
379  }
380 
381  num += ret;
382  }
383 
384  if (odp_unlikely(num == 0))
385  continue;
386 
387  events += num;
388  num_freed = 0;
389 
390  while (num_freed < num) {
391  num_free = num - num_freed;
392  if (num_free > max_burst)
393  num_free = max_burst;
394 
395  odp_buffer_free_multi(&buf[num_freed], num_free);
396  frees++;
397  num_freed += num_free;
398  }
399  }
400 
401  c2 = odp_cpu_cycles();
402  t2 = odp_time_local();
403 
404  nsec = odp_time_diff_ns(t2, t1);
405  cycles = odp_cpu_cycles_diff(c2, c1);
406 
407  /* Update stats*/
408  global->stat[thr].rounds = rounds;
409  global->stat[thr].frees = frees;
410  global->stat[thr].events = events;
411  global->stat[thr].nsec = nsec;
412  global->stat[thr].cycles = cycles;
413 
414  return 0;
415 }
416 
417 static int test_packet_pool(void *arg)
418 {
419  int ret, thr;
420  uint32_t num, num_free, num_freed, i, rounds;
421  uint64_t c1, c2, cycles, nsec;
422  uint64_t events, frees;
423  odp_time_t t1, t2;
424  test_global_t *global = arg;
425  test_options_t *test_options = &global->test_options;
426  uint32_t num_round = test_options->num_round;
427  uint32_t max_burst = test_options->max_burst;
428  uint32_t num_burst = test_options->num_burst;
429  uint32_t max_num = num_burst * max_burst;
430  uint32_t data_size = test_options->data_size;
431  odp_pool_t pool = global->pool;
432  odp_packet_t pkt[max_num];
433 
434  thr = odp_thread_id();
435 
436  for (i = 0; i < max_num; i++)
437  pkt[i] = ODP_PACKET_INVALID;
438 
439  events = 0;
440  frees = 0;
441  ret = 0;
442 
443  /* Start all workers at the same time */
444  odp_barrier_wait(&global->barrier);
445 
446  t1 = odp_time_local();
447  c1 = odp_cpu_cycles();
448 
449  for (rounds = 0; rounds < num_round; rounds++) {
450  num = 0;
451 
452  for (i = 0; i < num_burst; i++) {
453  ret = odp_packet_alloc_multi(pool, data_size, &pkt[num],
454  max_burst);
455  if (odp_unlikely(ret < 0)) {
456  printf("Error: Alloc failed. Round %u\n",
457  rounds);
458 
459  if (num)
460  odp_packet_free_multi(pkt, num);
461 
462  return -1;
463  }
464 
465  num += ret;
466  }
467 
468  if (odp_unlikely(num == 0))
469  continue;
470 
471  events += num;
472  num_freed = 0;
473 
474  while (num_freed < num) {
475  num_free = num - num_freed;
476  if (num_free > max_burst)
477  num_free = max_burst;
478 
479  odp_packet_free_multi(&pkt[num_freed], num_free);
480  frees++;
481  num_freed += num_free;
482  }
483  }
484 
485  c2 = odp_cpu_cycles();
486  t2 = odp_time_local();
487 
488  nsec = odp_time_diff_ns(t2, t1);
489  cycles = odp_cpu_cycles_diff(c2, c1);
490 
491  /* Update stats*/
492  global->stat[thr].rounds = rounds;
493  global->stat[thr].frees = frees;
494  global->stat[thr].events = events;
495  global->stat[thr].nsec = nsec;
496  global->stat[thr].cycles = cycles;
497 
498  return 0;
499 }
500 
501 static int start_workers(test_global_t *global, odp_instance_t instance)
502 {
503  odph_thread_common_param_t thr_common;
504  odph_thread_param_t thr_param;
505  test_options_t *test_options = &global->test_options;
506  int num_cpu = test_options->num_cpu;
507  int packet_pool = test_options->pool_type;
508 
509  odph_thread_common_param_init(&thr_common);
510  thr_common.instance = instance;
511  thr_common.cpumask = &global->cpumask;
512  thr_common.share_param = 1;
513 
514  odph_thread_param_init(&thr_param);
515  thr_param.arg = global;
516  thr_param.thr_type = ODP_THREAD_WORKER;
517 
518  if (packet_pool)
519  thr_param.start = test_packet_pool;
520  else
521  thr_param.start = test_buffer_pool;
522 
523  if (odph_thread_create(global->thread_tbl, &thr_common, &thr_param,
524  num_cpu) != num_cpu)
525  return -1;
526 
527  return 0;
528 }
529 
530 static void test_stats_perf(test_global_t *global)
531 {
532  odp_pool_stats_t stats;
533  odp_time_t t1, t2;
534  uint64_t nsec;
535  int i;
536  int num_thr = global->test_options.num_cpu + 1; /* workers + main thread */
537  odp_pool_t pool = global->pool;
538  double nsec_ave = 0.0;
539  const int rounds = 1000;
540 
541  if (num_thr > ODP_POOL_MAX_THREAD_STATS)
542  num_thr = ODP_POOL_MAX_THREAD_STATS;
543 
544  memset(&stats, 0, sizeof(odp_pool_stats_t));
545  stats.thread.first = 0;
546  stats.thread.last = num_thr - 1;
547 
548  t1 = odp_time_local_strict();
549 
550  for (i = 0; i < rounds; i++) {
551  if (odp_pool_stats(pool, &stats)) {
552  printf("Error: Stats request failed on round %i\n", i);
553  break;
554  }
555  }
556 
557  t2 = odp_time_local_strict();
558  nsec = odp_time_diff_ns(t2, t1);
559 
560  if (i > 0)
561  nsec_ave = (double)nsec / i;
562 
563  printf("Pool statistics:\n");
564  printf(" odp_pool_stats() calls %i\n", i);
565  printf(" ave call latency %.2f nsec\n", nsec_ave);
566  printf(" num threads %i\n", num_thr);
567  printf(" alloc_ops %" PRIu64 "\n", stats.alloc_ops);
568  printf(" free_ops %" PRIu64 "\n", stats.free_ops);
569  printf(" total_ops %" PRIu64 "\n", stats.total_ops);
570  printf(" available %" PRIu64 "\n", stats.available);
571  printf(" cache_available %" PRIu64 "\n", stats.cache_available);
572  for (i = 0; i < num_thr; i++) {
573  printf(" thr[%2i] cache_available %" PRIu64 "\n",
574  i, stats.thread.cache_available[i]);
575  }
576 
577  printf("\n");
578 }
579 
580 static int output_results(test_global_t *global)
581 {
582  int i, num;
583  double rounds_ave, allocs_ave, frees_ave;
584  double events_ave, nsec_ave, cycles_ave;
585  test_options_t *test_options = &global->test_options;
586  int num_cpu = test_options->num_cpu;
587  uint32_t num_burst = test_options->num_burst;
588  uint64_t rounds_sum = 0;
589  uint64_t frees_sum = 0;
590  uint64_t events_sum = 0;
591  uint64_t nsec_sum = 0;
592  uint64_t cycles_sum = 0;
593 
594  /* Averages */
595  for (i = 0; i < ODP_THREAD_COUNT_MAX; i++) {
596  rounds_sum += global->stat[i].rounds;
597  frees_sum += global->stat[i].frees;
598  events_sum += global->stat[i].events;
599  nsec_sum += global->stat[i].nsec;
600  cycles_sum += global->stat[i].cycles;
601  }
602 
603  if (rounds_sum == 0) {
604  printf("No results.\n");
605  return 0;
606  }
607 
608  rounds_ave = rounds_sum / num_cpu;
609  allocs_ave = (num_burst * rounds_sum) / num_cpu;
610  frees_ave = frees_sum / num_cpu;
611  events_ave = events_sum / num_cpu;
612  nsec_ave = nsec_sum / num_cpu;
613  cycles_ave = cycles_sum / num_cpu;
614  num = 0;
615 
616  printf("RESULTS - per thread (Million events per sec):\n");
617  printf("----------------------------------------------\n");
618  printf(" 1 2 3 4 5 6 7 8 9 10");
619 
620  for (i = 0; i < ODP_THREAD_COUNT_MAX; i++) {
621  if (global->stat[i].rounds) {
622  if ((num % 10) == 0)
623  printf("\n ");
624 
625  printf("%6.1f ", (1000.0 * global->stat[i].events) /
626  global->stat[i].nsec);
627  num++;
628  }
629  }
630  printf("\n\n");
631 
632  printf("RESULTS - average over %i threads:\n", num_cpu);
633  printf("----------------------------------\n");
634  printf(" alloc calls: %.3f\n", allocs_ave);
635  printf(" free calls: %.3f\n", frees_ave);
636  printf(" duration: %.3f msec\n", nsec_ave / 1000000);
637  printf(" num cycles: %.3f M\n", cycles_ave / 1000000);
638  printf(" cycles per round: %.3f\n",
639  cycles_ave / rounds_ave);
640  printf(" cycles per event: %.3f\n",
641  cycles_ave / events_ave);
642  printf(" ave events allocated: %.3f\n",
643  events_ave / allocs_ave);
644  printf(" allocs per sec: %.3f M\n",
645  (1000.0 * allocs_ave) / nsec_ave);
646  printf(" frees per sec: %.3f M\n",
647  (1000.0 * frees_ave) / nsec_ave);
648  printf(" events per sec: %.3f M\n\n",
649  (1000.0 * events_ave) / nsec_ave);
650 
651  printf("TOTAL events per sec: %.3f M\n\n",
652  (1000.0 * events_sum) / nsec_ave);
653 
654  if (global->common_options.is_export) {
655  if (test_common_write("alloc calls,free calls,duration (msec),"
656  "num cycles (M),cycles per round,cycles per event,"
657  "ave events allocated,allocs per sec (M),frees per sec (M),"
658  "events per sec (M),TOTAL events per sec (M)\n")) {
659  ODPH_ERR("Export failed\n");
660  test_common_write_term();
661  return -1;
662  }
663 
664  if (test_common_write("%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
665  allocs_ave, frees_ave, nsec_ave / 1000000,
666  cycles_ave / 1000000, cycles_ave / rounds_ave,
667  cycles_ave / events_ave, events_ave / allocs_ave,
668  (1000.0 * allocs_ave) / nsec_ave,
669  (1000.0 * frees_ave) / nsec_ave,
670  (1000.0 * events_ave) / nsec_ave,
671  (1000.0 * events_sum) / nsec_ave)) {
672  ODPH_ERR("Export failed\n");
673  test_common_write_term();
674  return -1;
675  }
676 
677  test_common_write_term();
678  }
679 
680  return 0;
681 }
682 
683 int main(int argc, char **argv)
684 {
685  odph_helper_options_t helper_options;
686  odp_instance_t instance;
687  odp_init_t init;
688  odp_shm_t shm;
689  test_global_t *global;
690  test_common_options_t common_options;
691 
692  /* Let helper collect its own arguments (e.g. --odph_proc) */
693  argc = odph_parse_options(argc, argv);
694  if (odph_options(&helper_options)) {
695  ODPH_ERR("Error: Reading ODP helper options failed.\n");
696  exit(EXIT_FAILURE);
697  }
698 
699  argc = test_common_parse_options(argc, argv);
700  if (test_common_options(&common_options)) {
701  ODPH_ERR("Error: Reading test options failed\n");
702  exit(EXIT_FAILURE);
703  }
704 
705  /* List features not to be used */
706  odp_init_param_init(&init);
707  init.not_used.feat.cls = 1;
708  init.not_used.feat.compress = 1;
709  init.not_used.feat.crypto = 1;
710  init.not_used.feat.ipsec = 1;
711  init.not_used.feat.schedule = 1;
712  init.not_used.feat.timer = 1;
713  init.not_used.feat.tm = 1;
714 
715  init.mem_model = helper_options.mem_model;
716 
717  /* Init ODP before calling anything else */
718  if (odp_init_global(&instance, &init, NULL)) {
719  printf("Error: Global init failed.\n");
720  return -1;
721  }
722 
723  /* Init this thread */
724  if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
725  printf("Error: Local init failed.\n");
726  return -1;
727  }
728 
729  shm = odp_shm_reserve("pool_perf_global", sizeof(test_global_t), ODP_CACHE_LINE_SIZE, 0);
730  if (shm == ODP_SHM_INVALID) {
731  ODPH_ERR("Error: Shared mem reserve failed.\n");
732  exit(EXIT_FAILURE);
733  }
734 
735  global = odp_shm_addr(shm);
736  if (global == NULL) {
737  ODPH_ERR("Error: Shared mem alloc failed\n");
738  exit(EXIT_FAILURE);
739  }
740 
741  memset(global, 0, sizeof(test_global_t));
742  global->pool = ODP_POOL_INVALID;
743 
744  global->common_options = common_options;
745 
746  if (parse_options(argc, argv, &global->test_options))
747  return -1;
748 
750 
751  if (set_num_cpu(global))
752  return -1;
753 
754  if (create_pool(global))
755  return -1;
756 
757  /* Start workers */
758  start_workers(global, instance);
759 
760  /* Wait workers to exit */
761  odph_thread_join(global->thread_tbl, global->test_options.num_cpu);
762 
763  if (global->test_options.stats_mode)
764  test_stats_perf(global);
765 
766  if (output_results(global))
767  return -1;
768 
769  if (odp_pool_destroy(global->pool)) {
770  printf("Error: Pool destroy failed.\n");
771  return -1;
772  }
773 
774  if (odp_shm_free(shm)) {
775  ODPH_ERR("Error: Shared mem free failed.\n");
776  exit(EXIT_FAILURE);
777  }
778 
779  if (odp_term_local()) {
780  printf("Error: term local failed.\n");
781  return -1;
782  }
783 
784  if (odp_term_global(instance)) {
785  printf("Error: term global failed.\n");
786  return -1;
787  }
788 
789  return 0;
790 }
void odp_barrier_init(odp_barrier_t *barr, int count)
Initialize barrier with thread count.
void odp_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
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.
#define odp_unlikely(x)
Branch unlikely taken.
Definition: spec/hints.h:64
uint64_t odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
CPU cycle count difference.
uint64_t odp_cpu_cycles(void)
Current CPU cycle count.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
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.
#define ODP_PACKET_INVALID
Invalid packet.
void odp_packet_free_multi(const odp_packet_t pkt[], int num)
Free multiple packets.
int odp_packet_alloc_multi(odp_pool_t pool, uint32_t len, odp_packet_t pkt[], int num)
Allocate multiple packets from a packet pool.
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_MAX_THREAD_STATS
Maximum number of per thread statistics a single odp_pool_stats() call can read.
int odp_pool_stats(odp_pool_t pool, odp_pool_stats_t *stats)
Read pool statistics.
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_BUFFER
Buffer pool.
@ ODP_POOL_PACKET
Packet pool.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_INVALID
Invalid shared memory block.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
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.
#define ODP_THREAD_COUNT_MAX
Maximum number of threads supported in build time.
int odp_thread_id(void)
Get thread identifier.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
odp_time_t odp_time_local(void)
Current local time.
odp_time_t odp_time_local_strict(void)
Current local time (strict)
uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
Time difference in nanoseconds.
The OpenDataPlane API.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
odp_feature_t not_used
Unused features.
struct odp_pool_capability_t::@121 buf
Buffer pool capabilities
struct odp_pool_capability_t::@122 pkt
Packet pool capabilities
uint32_t max_num
Maximum number of buffers of any size.
uint32_t min_cache_size
Minimum size of thread local cache.
uint32_t max_size
Maximum buffer data size in bytes.
odp_pool_stats_opt_t stats
Supported statistics counters.
uint32_t max_cache_size
Maximum size of thread local cache.
uint32_t max_len
Maximum packet data length in bytes.
Pool parameters.
uint32_t num
Number of buffers in the pool.
uint32_t max_len
Maximum packet length that will be allocated from the pool.
uint32_t cache_size
Maximum number of buffers cached locally per thread.
uint32_t size
Minimum buffer size in bytes.
uint32_t max_num
Maximum number of packets.
odp_pool_type_t type
Pool type.
uint32_t len
Minimum length of 'num' packets.
struct odp_pool_param_t::@126 pkt
Parameters for packet pools.
odp_pool_stats_opt_t stats
Configure statistics counters.
struct odp_pool_param_t::@125 buf
Parameters for buffer pools.
Pool statistics counters.
uint64_t alloc_ops
The number of alloc operations from the pool.
uint64_t available
The number of available events in the pool.
uint16_t first
First thread identifier to read counters from.
struct odp_pool_stats_t::@120 thread
Per thread counters.
uint64_t free_ops
The number of free operations to the pool.
uint64_t total_ops
The total number of alloc and free operations.
uint64_t cache_available
The number of available events in the local caches of all threads.
uint16_t last
Last thread identifier to read counters from.
uint32_t tm
Traffic Manager APIs, e.g., odp_tm_xxx()
uint32_t crypto
Crypto APIs, e.g., odp_crypto_xxx()
uint32_t ipsec
IPsec APIs, e.g., odp_ipsec_xxx()
uint32_t timer
Timer APIs, e.g., odp_timer_xxx(), odp_timeout_xxx()
uint32_t cls
Classifier APIs, e.g., odp_cls_xxx(), odp_cos_xxx()
uint32_t schedule
Scheduler APIs, e.g., odp_schedule_xxx()
struct odp_feature_t::@148 feat
Individual feature bits.
uint32_t compress
Compression APIs, e.g., odp_comp_xxx()
Pool statistics counters options.
uint64_t total_ops
See odp_pool_stats_t::total_ops.
uint64_t cache_available
See odp_pool_stats_t::cache_available.
struct odp_pool_stats_opt_t::@119 bit
Option flags.
uint64_t thread_cache_available
See odp_pool_stats_t::thread::cache_available.
uint64_t free_ops
See odp_pool_stats_t::free_ops.
uint64_t alloc_ops
See odp_pool_stats_t::alloc_ops.
uint64_t available
See odp_pool_stats_t::available.
uint64_t all
All bits of the bit field structure.