24 #include <odp/helper/odph_api.h>
26 #include <export_results.h>
28 #define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1)
29 #define MAX_QUEUES 1024
30 #define MAX_FILENAME 128
40 typedef struct test_opt_t {
42 unsigned long long period_ns;
44 unsigned long long res_hz;
45 unsigned long long offset_ns;
46 unsigned long long max_tmo_ns;
47 unsigned long long num;
48 unsigned long long num_warmup;
49 unsigned long long burst;
50 unsigned long long burst_gap;
52 unsigned long long max_multiplier;
53 unsigned long long multiplier;
69 uint64_t warmup_timers;
71 uint64_t alloc_timers;
72 char filename[MAX_FILENAME];
83 uint64_t first_period;
84 int64_t first_tmo_diff;
90 uint64_t nsec_before_sum;
91 uint64_t nsec_before_min;
92 uint64_t nsec_before_min_idx;
93 uint64_t nsec_before_max;
94 uint64_t nsec_before_max_idx;
96 uint64_t nsec_after_sum;
97 uint64_t nsec_after_min;
98 uint64_t nsec_after_min_idx;
99 uint64_t nsec_after_max;
100 uint64_t nsec_after_max_idx;
106 uint64_t num_too_near;
110 typedef struct test_log_t {
117 typedef struct test_global_t {
120 test_stat_t stat[MAX_WORKERS];
126 timer_ctx_t *timer_ctx;
130 uint64_t period_tick;
138 test_common_options_t common_options;
141 static void print_usage(
void)
144 "Timer accuracy test application.\n"
147 " -c, --count <num> CPU count, 0=all available, default=1\n"
148 " -p, --period <nsec> Timeout period in nsec. Not used in periodic mode. Default: 200 msec\n"
149 " -r, --res_ns <nsec> Timeout resolution in nsec. Default value is 0. Special values:\n"
150 " 0: Use period / 10 as the resolution\n"
151 " -1: In periodic mode, use resolution from capabilities\n"
152 " -R, --res_hz <hertz> Timeout resolution in hertz. Set resolution either with -r (nsec) or -R (hertz),\n"
153 " and leave other to 0. Default: 0 (not used)\n"
154 " -f, --first <nsec> First timer offset in nsec. Not used in concurrency mode. Default: 0 for\n"
155 " periodic mode, otherwise 300 msec\n"
156 " -x, --max_tmo <nsec> Maximum timeout in nsec. Not used in periodic mode.\n"
157 " When 0, max tmo is calculated from other options. Default: 0\n"
158 " -n, --num <number> Number of timeout periods. Default: 50\n"
159 " -w, --warmup <number> Number of warmup periods. Default: 0\n"
160 " -b, --burst <number> Number of timers per a timeout period. Default: 1\n"
161 " -g, --burst_gap <nsec> Gap (in nsec) between timers within a burst. Default: 0\n"
162 " In periodic mode, first + burst * burst_gap must be less than period length.\n"
163 " -m, --mode <number> Test mode select (default: 0):\n"
164 " 0: One-shot. Start all timers at init phase.\n"
165 " 1: One-shot. Each period, restart timers with absolute time.\n"
166 " 2: One-shot. Each period, restart timers with relative time.\n"
169 " -o, --output <file> Output file for measurement logs\n"
170 " -s, --clk_src Clock source select (default 0):\n"
171 " 0: ODP_CLOCK_DEFAULT\n"
172 " 1: ODP_CLOCK_SRC_1, ...\n"
173 " -t, --queue_type Queue sync type. Default is 0 (PARALLEL).\n"
177 " -q, --num_queue Number of queues. Default is 1.\n"
178 " -G, --sched_groups Use dedicated schedule group for each worker.\n"
179 " -i, --init Set global init parameters. Default: init params not set.\n"
180 " -h, --help Display help and exit.\n"
182 "ONE-SHOT MODE OPTIONS:\n"
183 " -e, --early_retry <num> When timer restart fails due to ODP_TIMER_TOO_NEAR, retry this many times\n"
184 " with expiration time incremented by the period. Default: 0\n"
186 "PERIODIC MODE OPTIONS:\n"
187 " -P, --periodic <freq_integer:freq_numer:freq_denom:max_multiplier>\n"
188 " Periodic timer pool parameters. Default: 5:0:0:1 (5 Hz)\n"
189 " -M, --multiplier Periodic timer multiplier. Default: 1\n"
191 "CONCURRENCY MODE OPTIONS:\n"
192 " -I, --interval <sec> Print interval information every <sec> seconds. Default: 1\n"
193 " -D, --max_diff <nsec> Print error if event is more than <nsec> nanoseconds late. Default: 0 (disabled)\n"
194 " -C, --cancel <n> Every <n> events, cancel the timer. Default: 0 (disabled)\n"
195 " -E, --switch_event <n> Every <n> events, free the received event and allocate a new one.\n"
196 " Default: 0 (disabled)\n"
197 " -T, --switch_timer <n> Every <n> events, free the timer and allocate a new one. Default: 0 (disabled)\n"
198 " -S, --cancel_start <n> Every <n> events, after starting a timer, immediately cancel and start again.\n"
199 " Default: 0 (disabled)\n"
200 " -X, --exit_on_error Exit on duplicate events and late timeouts.\n"
204 static int parse_options(
int argc,
char *argv[], test_opt_t *test_opt)
207 const struct option longopts[] = {
208 {
"count", required_argument, NULL,
'c'},
209 {
"period", required_argument, NULL,
'p'},
210 {
"res_ns", required_argument, NULL,
'r'},
211 {
"res_hz", required_argument, NULL,
'R'},
212 {
"first", required_argument, NULL,
'f'},
213 {
"max_tmo", required_argument, NULL,
'x'},
214 {
"num", required_argument, NULL,
'n'},
215 {
"warmup", required_argument, NULL,
'w'},
216 {
"burst", required_argument, NULL,
'b'},
217 {
"burst_gap", required_argument, NULL,
'g'},
218 {
"mode", required_argument, NULL,
'm'},
219 {
"periodic", required_argument, NULL,
'P'},
220 {
"multiplier", required_argument, NULL,
'M'},
221 {
"output", required_argument, NULL,
'o'},
222 {
"early_retry", required_argument, NULL,
'e'},
223 {
"clk_src", required_argument, NULL,
's'},
224 {
"queue_type", required_argument, NULL,
't'},
225 {
"num_queue", required_argument, NULL,
'q'},
226 {
"interval", required_argument, NULL,
'I'},
227 {
"max_diff", required_argument, NULL,
'D'},
228 {
"cancel", required_argument, NULL,
'C'},
229 {
"switch_event", required_argument, NULL,
'E'},
230 {
"switch_timer", required_argument, NULL,
'T'},
231 {
"cancel_start", required_argument, NULL,
'S'},
232 {
"exit_on_error", no_argument, NULL,
'X'},
233 {
"sched_groups", no_argument, NULL,
'G'},
234 {
"init", no_argument, NULL,
'i'},
235 {
"help", no_argument, NULL,
'h'},
238 const char *shortopts =
"+c:p:r:R:f:x:n:w:b:g:m:P:M:o:e:s:t:q:I:D:C:E:T:S:XGih";
241 memset(test_opt, 0,
sizeof(*test_opt));
243 test_opt->cpu_count = 1;
245 test_opt->offset_ns = UINT64_MAX;
248 test_opt->mode = MODE_ONESHOT;
250 test_opt->max_multiplier = 1;
251 test_opt->multiplier = 1;
254 test_opt->num_queue = 1;
255 test_opt->interval = 1;
258 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
265 test_opt->cpu_count = atoi(optarg);
268 test_opt->period_ns = strtoull(optarg, NULL, 0);
271 test_opt->res_ns = strtoll(optarg, NULL, 0);
274 test_opt->res_hz = strtoull(optarg, NULL, 0);
277 test_opt->offset_ns = strtoull(optarg, NULL, 0);
280 test_opt->max_tmo_ns = strtoull(optarg, NULL, 0);
283 test_opt->num = strtoull(optarg, NULL, 0);
286 test_opt->num_warmup = strtoull(optarg, NULL, 0);
289 test_opt->burst = strtoull(optarg, NULL, 0);
292 test_opt->burst_gap = strtoull(optarg, NULL, 0);
295 test_opt->mode = atoi(optarg);
298 sscanf(optarg,
"%" SCNu64
":%" SCNu64
":%" SCNu64
":%llu",
299 &test_opt->freq.integer, &test_opt->freq.numer,
300 &test_opt->freq.denom, &test_opt->max_multiplier);
303 test_opt->multiplier = strtoull(optarg, NULL, 0);
306 test_opt->output = 1;
307 if (strlen(optarg) >= MAX_FILENAME) {
308 ODPH_ERR(
"Filename too long\n");
311 odph_strcpy(test_opt->filename, optarg, MAX_FILENAME);
314 test_opt->early_retry = atoi(optarg);
317 test_opt->clk_src = atoi(optarg);
320 switch (atoi(optarg)) {
333 test_opt->num_queue = atoi(optarg);
336 test_opt->interval = atoi(optarg);
339 test_opt->max_diff = atoi(optarg);
342 test_opt->cancel = atoi(optarg);
345 test_opt->switch_event = atoi(optarg);
348 test_opt->switch_timer = atoi(optarg);
351 test_opt->cancel_start = atoi(optarg);
354 test_opt->exit_on_error = 1;
357 test_opt->groups = 1;
373 if (test_opt->mode == MODE_PERIODIC) {
374 if ((test_opt->freq.integer == 0 && test_opt->freq.numer == 0) ||
375 (test_opt->freq.numer != 0 && test_opt->freq.denom == 0)) {
376 ODPH_ERR(
"Bad frequency\n");
380 test_opt->period_ns =
383 if (test_opt->offset_ns == UINT64_MAX)
384 test_opt->offset_ns = 0;
386 if (test_opt->res_ns < 0) {
387 ODPH_ERR(
"Resolution (res_ns) must be >= 0 with single shot timer\n");
391 if (test_opt->offset_ns == UINT64_MAX)
394 if (test_opt->mode == MODE_CONCURRENCY)
395 test_opt->offset_ns = 0;
398 test_opt->warmup_timers = test_opt->num_warmup * test_opt->burst;
399 test_opt->tot_timers =
400 test_opt->warmup_timers + test_opt->num * test_opt->burst;
402 if (test_opt->mode == MODE_ONESHOT)
403 test_opt->alloc_timers = test_opt->tot_timers;
405 test_opt->alloc_timers = test_opt->burst;
413 uint64_t res_ns, res_hz;
414 uint64_t max_res_ns, max_res_hz;
415 uint64_t period_ns = test_global->opt.period_ns;
416 uint64_t num_tmo = test_global->opt.num + test_global->opt.num_warmup;
417 uint64_t offset_ns = test_global->opt.offset_ns;
418 enum mode_e mode = test_global->opt.mode;
424 if (test_global->opt.res_ns == 0 && test_global->opt.res_hz == 0) {
425 res_ns = test_global->opt.period_ns / 10;
427 }
else if (test_global->opt.res_ns) {
428 res_ns = test_global->opt.res_ns;
432 res_hz = test_global->opt.res_hz;
435 if (res_ns && res_ns < max_res_ns) {
436 ODPH_ERR(
"Resolution %" PRIu64
" nsec too high.\n"
437 "Highest resolution %" PRIu64
438 " nsec. Default resolution is period / 10.\n\n",
443 if (res_hz && res_hz > max_res_hz) {
444 ODPH_ERR(
"Resolution %" PRIu64
" hz too high.\n"
445 "Highest resolution %" PRIu64
446 " hz. Default resolution is period / 10.\n\n",
452 timer_param->
res_ns = res_ns;
454 timer_param->
res_hz = res_hz;
456 if (mode == MODE_ONESHOT) {
457 timer_param->
min_tmo = offset_ns / 2;
458 timer_param->
max_tmo = offset_ns + ((num_tmo + 1) * period_ns);
460 if (mode == MODE_RESTART_ABS)
461 timer_param->
min_tmo = period_ns / 10;
463 timer_param->
min_tmo = period_ns;
464 timer_param->
max_tmo = offset_ns + (2 * period_ns);
467 if (test_global->opt.max_tmo_ns) {
468 if (test_global->opt.max_tmo_ns < timer_param->
max_tmo) {
469 ODPH_ERR(
"Max tmo is too small. Must be at least %" PRIu64
" nsec.\n",
474 timer_param->
max_tmo = test_global->opt.max_tmo_ns;
477 printf(
" period: %" PRIu64
" nsec\n", period_ns);
478 printf(
" max res nsec: %" PRIu64
"\n", max_res_ns);
479 printf(
" max res hertz: %" PRIu64
"\n", max_res_hz);
481 test_global->period_dbl = period_ns;
492 double freq_dbl, min_freq, max_freq;
495 uint64_t res_hz = test_global->opt.res_hz;
496 uint64_t max_multiplier = test_global->opt.max_multiplier;
497 uint64_t multiplier = test_global->opt.multiplier;
502 res_ns = test_global->opt.res_ns;
510 ODPH_ERR(
"Resolution too high\n");
515 if (test_global->opt.res_ns < 0)
528 ODPH_ERR(
"Requested periodic timer capabilities are not supported.\n"
529 "Capabilities: min base freq %g Hz, max base freq %g Hz, "
530 "max res %" PRIu64
" Hz\n",
536 printf(
"Requested base frequency is not met. Using %.2f Hz instead of %.2f Hz.\n",
546 test_global->base_freq = freq;
555 timer_param->
res_hz = res_hz;
557 timer_param->
res_ns = res_ns;
559 printf(
" min freq capa: %.2f hz\n", min_freq);
560 printf(
" max freq capa: %.2f hz\n", max_freq);
561 printf(
" freq option: %.2f hz\n", opt_freq);
562 printf(
" freq: %.2f hz\n", freq_dbl);
563 printf(
" freq integer: %" PRIu64
"\n", freq.
integer);
564 printf(
" freq numer: %" PRIu64
"\n", freq.
numer);
565 printf(
" freq denom: %" PRIu64
"\n", freq.
denom);
566 printf(
" max_multiplier: %" PRIu64
"\n", max_multiplier);
567 printf(
" multiplier: %" PRIu64
"\n", multiplier);
568 printf(
" timer freq: %.2f hz\n", multiplier * freq_dbl);
569 printf(
" timer period: %.2f nsec\n", test_global->period_dbl);
570 printf(
" resolution capa: %" PRIu64
" nsec\n", capa.
res_ns);
575 static int create_timers(test_global_t *test_global)
590 uint64_t i, num_tmo, num_warmup, burst, burst_gap;
591 uint64_t tot_timers, alloc_timers;
596 mode = test_global->opt.mode;
597 alloc_timers = test_global->opt.alloc_timers;
598 tot_timers = test_global->opt.tot_timers;
599 num_warmup = test_global->opt.num_warmup;
600 num_tmo = num_warmup + test_global->opt.num;
601 burst = test_global->opt.burst;
602 burst_gap = test_global->opt.burst_gap;
603 offset_ns = test_global->opt.offset_ns;
604 queue = test_global->queue;
605 group = test_global->group;
611 for (i = 0; i < alloc_timers; i++) {
616 if (test_global->opt.groups) {
623 for (i = 0; i < (uint64_t)test_global->opt.cpu_count; i++) {
627 ODPH_ERR(
"Group create failed.\n");
636 queue_param.
sched.
sync = test_global->opt.queue_type;
639 for (i = 0; i < (uint64_t)test_global->opt.num_queue; i++) {
640 if (test_global->opt.groups)
641 queue_param.
sched.
group = group[i % test_global->opt.cpu_count];
645 ODPH_ERR(
"Queue create failed.\n");
652 pool_param.
tmo.
num = alloc_timers + pool_param.
tmo.
cache_size * test_global->opt.cpu_count;
653 if (mode == MODE_CONCURRENCY)
654 pool_param.
tmo.
num += test_global->opt.cpu_count;
659 ODPH_ERR(
"Timeout pool create failed.\n");
663 test_global->timeout_pool = pool;
664 clk_src = test_global->opt.clk_src;
667 ODPH_ERR(
"Timer capa failed\n");
673 if (mode == MODE_PERIODIC) {
675 ODPH_ERR(
"Periodic timers not supported.\n");
681 printf(
"\nTest parameters:\n");
682 printf(
" clock source: %i\n", clk_src);
683 printf(
" max timers capa: %" PRIu32
"\n", max_timers);
684 printf(
" mode: %i\n", mode);
685 printf(
" queue type: %i\n", test_global->opt.queue_type);
686 printf(
" num queue: %i\n", test_global->opt.num_queue);
687 printf(
" sched groups: %s\n", test_global->opt.groups ?
"yes" :
"no");
691 if (mode == MODE_PERIODIC)
692 ret = periodic_params(test_global, &timer_param, &timer_capa);
694 ret = single_shot_params(test_global, &timer_param, &timer_capa);
700 test_global->res_ns = 1000000000.0 / timer_param.
res_hz;
701 printf(
" resolution: %" PRIu64
" Hz\n", timer_param.
res_hz);
703 test_global->res_ns = timer_param.
res_ns;
704 printf(
" resolution: %" PRIu64
" nsec\n", timer_param.
res_ns);
708 if (mode == MODE_CONCURRENCY)
709 timer_param.
num_timers += test_global->opt.cpu_count;
711 if (max_timers && timer_param.
num_timers > max_timers) {
712 ODPH_ERR(
"Too many timers: %" PRIu64
" (max %u)\n", test_global->opt.alloc_timers,
719 printf(
" restart retries: %i\n", test_global->opt.early_retry);
720 if (test_global->opt.output)
721 printf(
" log file: %s\n", test_global->opt.filename);
722 printf(
" start offset: %" PRIu64
" nsec\n", offset_ns);
723 printf(
" min timeout: %" PRIu64
" nsec\n", timer_param.
min_tmo);
724 printf(
" max timeout: %" PRIu64
" nsec\n", timer_param.
max_tmo);
725 printf(
" num timeout: %" PRIu64
"\n", num_tmo);
726 printf(
" num warmup: %" PRIu64
"\n", num_warmup);
727 printf(
" burst size: %" PRIu64
"\n", burst);
728 printf(
" burst gap: %" PRIu64
"\n", burst_gap);
729 printf(
" total timers: %" PRIu64
"\n", tot_timers);
730 printf(
" warmup timers: %" PRIu64
"\n", test_global->opt.warmup_timers);
731 printf(
" alloc timers: %" PRIu64
"\n", alloc_timers);
732 printf(
" warmup time: %.2f sec\n",
733 (offset_ns + (num_warmup * test_global->period_dbl)) / 1000000000.0);
734 printf(
" test run time: %.2f sec\n\n",
735 (offset_ns + (num_tmo * test_global->period_dbl)) / 1000000000.0);
740 ODPH_ERR(
"Timer pool create failed\n");
745 ODPH_ERR(
"Timer pool start failed\n");
754 test_global->timer_pool = timer_pool;
756 for (i = 0; i < alloc_timers; i++) {
757 timer_ctx_t *ctx = &test_global->timer_ctx[i];
759 timer =
odp_timer_alloc(timer_pool, queue[i % test_global->opt.num_queue], ctx);
762 ODPH_ERR(
"Timer alloc failed.\n");
770 ODPH_ERR(
"Timeout alloc failed\n");
780 for (i = 0; i < 1000; i++) {
784 ODPH_ERR(
"Spurious event received\n");
793 static int start_timers(test_global_t *test_global)
797 uint64_t period_ns, start_ns, nsec, offset_ns;
799 uint64_t i, j, idx, num_tmo, num_warmup, burst, burst_gap;
802 mode = test_global->opt.mode;
803 num_warmup = test_global->opt.num_warmup;
804 num_tmo = num_warmup + test_global->opt.num;
805 burst = test_global->opt.burst;
806 burst_gap = test_global->opt.burst_gap;
807 period_ns = test_global->opt.period_ns;
808 offset_ns = test_global->opt.offset_ns;
809 timer_pool = test_global->timer_pool;
820 test_global->start_tick = start_tick;
821 test_global->start_ns = start_ns;
825 if (mode != MODE_ONESHOT)
828 for (i = 0; i < num_tmo; i++) {
831 for (j = 0; j < burst; j++) {
832 timer_ctx_t *ctx = &test_global->timer_ctx[idx];
835 if (mode == MODE_PERIODIC) {
838 nsec = offset_ns + (j * burst_gap);
842 ctx->nsec = start_ns + test_global->period_dbl + 0.5;
844 ctx->nsec = start_ns + nsec;
846 ctx->first_period = start_tick +
848 test_global->period_dbl + 0.5);
854 periodic_start.
tmo_ev = ctx->event;
856 }
else if (mode == MODE_CONCURRENCY) {
857 ctx->nsec = start_ns + test_global->opt.period_ns;
859 start_param.
tick = test_global->period_tick;
860 start_param.
tmo_ev = ctx->event;
864 nsec = offset_ns + (i * period_ns) + (j * burst_gap);
865 ctx->nsec = start_ns + nsec;
869 start_param.
tmo_ev = ctx->event;
874 ODPH_ERR(
"Timer[%" PRIu64
"] set failed: %i\n", idx, retval);
887 static int destroy_timers(test_global_t *test_global)
889 uint64_t i, alloc_timers;
893 alloc_timers = test_global->opt.alloc_timers;
895 for (i = 0; i < alloc_timers; i++) {
896 timer = test_global->timer_ctx[i].timer;
902 ODPH_ERR(
"Timer free failed: %" PRIu64
"\n", i);
912 ODPH_ERR(
"Pool destroy failed.\n");
917 for (i = 0; i < (uint64_t)test_global->opt.num_queue; i++) {
919 ODPH_ERR(
"Queue destroy failed.\n");
924 if (test_global->opt.groups) {
925 for (i = 0; i < (uint64_t)test_global->opt.cpu_count; i++) {
927 ODPH_ERR(
"Group destroy failed.\n");
936 static void print_nsec_error(
const char *str, int64_t nsec,
double res_ns,
939 printf(
" %s: %12" PRIi64
" / %.3fx resolution",
940 str, nsec, (
double)nsec / res_ns);
942 printf(
", thread %d", tid);
944 printf(
", event %d", idx);
948 static int print_stat(test_global_t *test_global)
950 test_stat_t test_stat;
951 test_stat_t *stat = &test_stat;
953 test_stat_t *s = test_global->stat;
954 test_log_t *log = test_global->log;
955 double res_ns = test_global->res_ns;
956 uint64_t ave_after = 0;
957 uint64_t ave_before = 0;
958 uint64_t nsec_before_min_tid = 0;
959 uint64_t nsec_before_max_tid = 0;
960 uint64_t nsec_after_min_tid = 0;
961 uint64_t nsec_after_max_tid = 0;
963 memset(stat, 0,
sizeof(*stat));
964 stat->nsec_before_min = UINT64_MAX;
965 stat->nsec_after_min = UINT64_MAX;
967 for (
int i = 1; i < test_global->opt.cpu_count + 1; i++) {
968 stat->nsec_before_sum += s[i].nsec_before_sum;
969 stat->nsec_after_sum += s[i].nsec_after_sum;
970 stat->num_before += s[i].num_before;
971 stat->num_exact += s[i].num_exact;
972 stat->num_after += s[i].num_after;
973 stat->num_too_near += s[i].num_too_near;
975 if (s[i].nsec_before_min < stat->nsec_before_min) {
976 stat->nsec_before_min = s[i].nsec_before_min;
977 stat->nsec_before_min_idx = s[i].nsec_before_min_idx;
978 nsec_before_min_tid = i;
981 if (s[i].nsec_after_min < stat->nsec_after_min) {
982 stat->nsec_after_min = s[i].nsec_after_min;
983 stat->nsec_after_min_idx = s[i].nsec_after_min_idx;
984 nsec_after_min_tid = i;
987 if (s[i].nsec_before_max > stat->nsec_before_max) {
988 stat->nsec_before_max = s[i].nsec_before_max;
989 stat->nsec_before_max_idx = s[i].nsec_before_max_idx;
990 nsec_before_max_tid = i;
993 if (s[i].nsec_after_max > stat->nsec_after_max) {
994 stat->nsec_after_max = s[i].nsec_after_max;
995 stat->nsec_after_max_idx = s[i].nsec_after_max_idx;
996 nsec_after_max_tid = i;
1000 if (stat->num_after)
1001 ave_after = stat->nsec_after_sum / stat->num_after;
1003 stat->nsec_after_min = 0;
1005 if (stat->num_before)
1006 ave_before = stat->nsec_before_sum / stat->num_before;
1008 stat->nsec_before_min = 0;
1010 tot_timers = stat->num_before + stat->num_after + stat->num_exact;
1013 FILE *file = test_global->file;
1015 fprintf(file,
" Timer thread tmo(ns) diff(ns)\n");
1017 for (uint64_t i = 0; i < tot_timers; i++) {
1018 fprintf(file,
"%8" PRIu64
" %7u %12" PRIu64
" %10"
1019 PRIi64
"\n", i, log[i].tid, log[i].tmo_ns, log[i].diff_ns);
1022 fprintf(file,
"\n");
1025 printf(
"\nTest results:\n");
1026 printf(
" num after: %12" PRIu64
" / %.2f%%\n",
1027 stat->num_after, 100.0 * stat->num_after / tot_timers);
1028 printf(
" num before: %12" PRIu64
" / %.2f%%\n",
1029 stat->num_before, 100.0 * stat->num_before / tot_timers);
1030 printf(
" num exact: %12" PRIu64
" / %.2f%%\n",
1031 stat->num_exact, 100.0 * stat->num_exact / tot_timers);
1032 printf(
" num retry: %12" PRIu64
" / %.2f%%\n",
1033 stat->num_too_near, 100.0 * stat->num_too_near / tot_timers);
1034 printf(
" error after (nsec):\n");
1035 print_nsec_error(
"min", stat->nsec_after_min, res_ns, nsec_after_min_tid,
1036 stat->nsec_after_min_idx);
1037 print_nsec_error(
"max", stat->nsec_after_max, res_ns, nsec_after_max_tid,
1038 stat->nsec_after_max_idx);
1039 print_nsec_error(
"ave", ave_after, res_ns, -1, -1);
1040 printf(
" error before (nsec):\n");
1041 print_nsec_error(
"min", stat->nsec_before_min, res_ns, nsec_before_min_tid,
1042 stat->nsec_before_min_idx);
1043 print_nsec_error(
"max", stat->nsec_before_max, res_ns, nsec_before_max_tid,
1044 stat->nsec_before_max_idx);
1045 print_nsec_error(
"ave", ave_before, res_ns, -1, -1);
1047 if (test_global->opt.mode == MODE_PERIODIC && !test_global->opt.offset_ns) {
1051 for (
int i = 0; i < (int)test_global->opt.alloc_timers; i++) {
1052 timer_ctx_t *t = &test_global->timer_ctx[i];
1053 int64_t v = t->first_tmo_diff;
1055 if (ODPH_ABS(v) > ODPH_ABS(max)) {
1061 printf(
" first timeout difference to one period, based on %s (nsec):\n",
1062 test_global->timer_ctx[idx].tmo_tick ?
"timeout tick" :
"time");
1063 print_nsec_error(
"max", max, res_ns, -1, -1);
1068 for (
int i = 0; i < (int)test_global->opt.alloc_timers; i++) {
1069 timer_ctx_t *t = &test_global->timer_ctx[i];
1070 int64_t v = t->nsec_final;
1072 if (ODPH_ABS(v) > ODPH_ABS(max))
1076 printf(
" final timeout error (nsec):\n");
1077 print_nsec_error(
"max", max, res_ns, -1, -1);
1081 if (test_global->common_options.is_export) {
1082 if (test_common_write(
"num after,num before,num exact,num retry,"
1083 "error after min (nsec),error after min resolution,"
1084 "error after max (nsec),error after max resolution,"
1085 "error after ave (nsec),error after ave resolution,"
1086 "error before min (nsec),error before min resolution,"
1087 "error before max (nsec),error before max resolution,"
1088 "error before ave (nsec),error before ave resolution,"
1089 "final timeout error max (nsec),"
1090 "final timeout error max resolution\n")) {
1091 ODPH_ERR(
"Export failed\n");
1092 test_common_write_term();
1096 if (test_common_write(
"%" PRIu64
",%" PRIu64
",%" PRIu64
",%" PRIu64
",%" PRIu64
","
1097 "%f,%" PRIu64
",%f,%" PRIu64
",%f,%" PRIu64
",%f,%" PRIu64
","
1098 "%f,%" PRIu64
",%f,%" PRId64
",%f\n",
1099 stat->num_after, stat->num_before,
1100 stat->num_exact, stat->num_too_near,
1101 stat->nsec_after_min, (
double)stat->nsec_after_min / res_ns,
1102 stat->nsec_after_max, (
double)stat->nsec_after_max / res_ns,
1103 ave_after, (
double)ave_after / res_ns,
1104 stat->nsec_before_min, (
double)stat->nsec_before_min / res_ns,
1105 stat->nsec_before_max, (
double)stat->nsec_before_max / res_ns,
1106 ave_before, (
double)ave_before / res_ns,
1107 max, (
double)max / res_ns
1109 ODPH_ERR(
"Export failed\n");
1110 test_common_write_term();
1114 test_common_write_term();
1120 static void cancel_periodic_timers(test_global_t *test_global)
1122 uint64_t i, alloc_timers;
1125 alloc_timers = test_global->opt.alloc_timers;
1127 for (i = 0; i < alloc_timers; i++) {
1128 timer = test_global->timer_ctx[i].timer;
1134 ODPH_ERR(
"Failed to cancel periodic timer.\n");
1138 static void process_event_concurrency(uint64_t events, test_global_t *test_global, timer_ctx_t *ctx,
1145 const uint64_t period_ns = test_global->opt.period_ns;
1146 const uint64_t tick = test_global->period_tick;
1147 const int cancel_start =
1148 test_global->opt.cancel_start && !(events % test_global->opt.cancel_start);
1149 const int cancel = test_global->opt.cancel && !(events % test_global->opt.cancel);
1150 const int switch_timer =
1151 test_global->opt.switch_timer && !(events % test_global->opt.switch_timer);
1152 const int switch_event =
1153 test_global->opt.switch_event && !(events % test_global->opt.switch_event);
1166 ctx->nsec = time_ns + period_ns;
1179 "odp_timer_cancel() succeeded: event %p ctx %p sched event %p sched ctx %p\n",
1180 event, ev_ctx, ev, ctx);
1191 test_global->queue[events % test_global->opt.num_queue],
1194 ODPH_ERR(
"odp_timer_alloc() failed\n");
1198 ODPH_ERR(
"odp_timer_free()\n");
1212 ODPH_ERR(
"odp_timeout_alloc() failed\n");
1221 start_param.
tick = tick;
1226 ODPH_ERR(
"odp_timer_start(): %d\n", ret);
1238 ODPH_ERR(
"odp_timeout_alloc() failed\n");
1246 ODPH_ERR(
"odp_timer_start(): %d\n", ret);
1264 static int run_test(
void *arg)
1266 test_global_t *test_global = (test_global_t *)arg;
1269 uint64_t time_ns, diff_ns;
1276 test_log_t *log = test_global->log;
1277 enum mode_e mode = test_global->opt.mode;
1278 uint64_t tot_timers = test_global->opt.tot_timers;
1279 double period_dbl = test_global->period_dbl;
1283 if (tid > test_global->opt.cpu_count) {
1284 ODPH_ERR(
"tid %d is larger than cpu_count %d.\n", tid, test_global->opt.cpu_count);
1288 test_stat_t *stat = &test_global->stat[tid];
1290 memset(stat, 0,
sizeof(*stat));
1291 stat->nsec_before_min = UINT64_MAX;
1292 stat->nsec_after_min = UINT64_MAX;
1294 if (test_global->opt.groups) {
1297 group = test_global->group[tid - 1];
1300 ODPH_ERR(
"odp_schedule_group_join() failed\n");
1312 if (mode == MODE_PERIODIC) {
1314 test_global->opt.alloc_timers)
1329 if (mode == MODE_PERIODIC) {
1330 if (!ctx->events && !test_global->opt.offset_ns) {
1345 ctx->first_tmo_diff =
1348 tmo_ns += ctx->first_tmo_diff;
1354 ctx->first_tmo_diff = (int64_t)time_ns - (int64_t)tmo_ns;
1355 tmo_ns = ctx->nsec = time_ns;
1362 tmo_ns += ctx->events * period_dbl + 0.5;
1364 }
else if (mode == MODE_CONCURRENCY) {
1365 uint64_t events = ++ctx->events;
1366 uint64_t starts = ctx->starts;
1368 if (events > starts) {
1369 ODPH_ERR(
"ctx %p timer %p time %" PRIu64
" starts %" PRIu64
1370 " events %" PRIu64
"\n",
1371 ctx, ctx->timer, time_ns, starts, events);
1372 if (test_global->opt.exit_on_error)
1376 int64_t diff = (int64_t)time_ns - (int64_t)tmo_ns;
1378 if (test_global->opt.max_diff &&
1379 diff > (int64_t)test_global->opt.max_diff) {
1380 ODPH_ERR(
"ctx %p timer %p time %" PRIu64
" diff %" PRIi64
"\n", ctx,
1381 ctx->timer, time_ns, diff);
1382 if (test_global->opt.exit_on_error)
1389 if (events >= test_global->opt.warmup_timers && events < tot_timers) {
1390 uint64_t i = events - test_global->opt.warmup_timers;
1392 ctx->nsec_final = (int64_t)time_ns - (int64_t)tmo_ns;
1395 log[i].tmo_ns = tmo_ns;
1399 if (time_ns > tmo_ns) {
1400 diff_ns = time_ns - tmo_ns;
1402 stat->nsec_after_sum += diff_ns;
1403 if (diff_ns < stat->nsec_after_min) {
1404 stat->nsec_after_min = diff_ns;
1405 stat->nsec_after_min_idx = i;
1407 if (diff_ns > stat->nsec_after_max) {
1408 stat->nsec_after_max = diff_ns;
1409 stat->nsec_after_max_idx = i;
1412 log[i].diff_ns = diff_ns;
1414 }
else if (time_ns < tmo_ns) {
1415 diff_ns = tmo_ns - time_ns;
1417 stat->nsec_before_sum += diff_ns;
1418 if (diff_ns < stat->nsec_before_min) {
1419 stat->nsec_before_min = diff_ns;
1420 stat->nsec_before_min_idx = i;
1422 if (diff_ns > stat->nsec_before_max) {
1423 stat->nsec_before_max = diff_ns;
1424 stat->nsec_before_max_idx = i;
1427 log[i].diff_ns = -diff_ns;
1433 if ((mode == MODE_RESTART_ABS || mode == MODE_RESTART_REL) &&
1434 events < tot_timers - 1) {
1437 uint64_t nsec, tick;
1440 unsigned int retries = test_global->opt.early_retry;
1441 uint64_t start_ns = test_global->start_ns;
1442 uint64_t period_ns = test_global->opt.period_ns;
1449 for (j = 0; j < retries + 1; j++) {
1450 if (mode == MODE_RESTART_ABS) {
1452 ctx->nsec += period_ns;
1453 nsec = ctx->nsec - start_ns;
1454 tick = test_global->start_tick +
1459 tick = test_global->period_tick;
1462 ctx->nsec = time_ns + period_ns;
1467 start_param.
tick = tick;
1471 if (events >= test_global->opt.warmup_timers)
1472 stat->num_too_near++;
1479 ODPH_ERR(
"Timer set failed: %i. Timeout nsec "
1484 }
else if (mode == MODE_PERIODIC) {
1488 ODPH_ERR(
"Failed to ack a periodic timer.\n");
1493 if (ret == 2 || ret < 0)
1495 }
else if (mode == MODE_CONCURRENCY && events < tot_timers - 1) {
1496 process_event_concurrency(events, test_global, ctx, time_ns, ev);
1502 if (test_global->opt.groups) {
1504 ODPH_ERR(
"odp_schedule_group_leave() failed\n");
1510 static void interval_loop_concurrency(test_global_t *test_global)
1512 uint64_t events_prev = 0;
1513 uint64_t events = 0;
1515 uint64_t prev_ns = start_ns;
1517 while (events < test_global->opt.tot_timers) {
1525 uint64_t e = events - events_prev;
1527 printf(
"sec %" PRIu64
" total events %" PRIu64
" events %" PRIu64
1528 " events/s %" PRIu64
"\n", sec_total, events, e, e * 1000 / msec);
1529 events_prev = events;
1534 int main(
int argc,
char *argv[])
1538 test_opt_t test_opt;
1539 test_global_t *test_global;
1540 odph_helper_options_t helper_options;
1541 test_common_options_t common_options;
1546 argc = odph_parse_options(argc, argv);
1547 if (odph_options(&helper_options)) {
1548 ODPH_ERR(
"Reading ODP helper options failed.\n");
1552 argc = test_common_parse_options(argc, argv);
1553 if (test_common_options(&common_options)) {
1554 ODPH_ERR(
"Reading test options failed\n");
1558 if (parse_options(argc, argv, &test_opt))
1569 init.
mem_model = helper_options.mem_model;
1576 ODPH_ERR(
"Global init failed.\n");
1582 ODPH_ERR(
"Local init failed.\n");
1592 uint64_t size =
sizeof(test_global_t);
1598 ODPH_ERR(
"Shm alloc failed.\n");
1603 memset(test_global, 0, size);
1604 memcpy(&test_global->opt, &test_opt,
sizeof(test_opt_t));
1606 test_global->common_options = common_options;
1608 size = test_global->opt.alloc_timers *
sizeof(timer_ctx_t);
1613 ODPH_ERR(
"Timer context alloc failed.\n");
1619 memset(test_global->timer_ctx, 0, size);
1621 if (test_global->opt.output) {
1622 test_global->file = fopen(test_global->opt.filename,
"w");
1623 if (test_global->file == NULL) {
1624 ODPH_ERR(
"Failed to open output file %s: %s\n", test_global->opt.filename,
1630 size = (test_global->opt.tot_timers - test_global->opt.warmup_timers) *
1632 shm_log =
odp_shm_reserve(
"timer_accuracy_log", size,
sizeof(test_log_t),
1636 ODPH_ERR(
"Test log alloc failed.\n");
1642 memset(test_global->log, 0, size);
1645 odph_thread_t thread_tbl[MAX_WORKERS];
1649 odph_thread_common_param_t thr_common;
1650 odph_thread_param_t thr_param;
1652 memset(thread_tbl, 0,
sizeof(thread_tbl));
1654 num_workers = MAX_WORKERS;
1655 if (test_global->opt.cpu_count && test_global->opt.cpu_count < MAX_WORKERS)
1656 num_workers = test_global->opt.cpu_count;
1658 test_global->opt.cpu_count = num_workers;
1661 printf(
"num worker threads: %i\n", num_workers);
1663 printf(
"cpu mask: %s\n", cpumaskstr);
1665 ret = create_timers(test_global);
1673 odph_thread_param_init(&thr_param);
1674 thr_param.start = run_test;
1675 thr_param.arg = (
void *)test_global;
1678 odph_thread_common_param_init(&thr_common);
1679 thr_common.instance = instance;
1680 thr_common.cpumask = &cpumask;
1681 thr_common.share_param = 1;
1683 odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers);
1686 ret = start_timers(test_global);
1690 if (test_global->opt.mode == MODE_PERIODIC) {
1694 cancel_periodic_timers(test_global);
1695 }
else if (test_global->opt.mode == MODE_CONCURRENCY) {
1696 interval_loop_concurrency(test_global);
1699 odph_thread_join(thread_tbl, num_workers);
1701 ret = print_stat(test_global);
1706 if (test_global->file)
1707 fclose(test_global->file);
1709 if (destroy_timers(test_global))
1722 ODPH_ERR(
"Term local failed.\n");
1727 ODPH_ERR(
"Term global failed.\n");
void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val)
Initialize atomic uint64 variable.
void odp_atomic_inc_u64(odp_atomic_u64_t *atom)
Increment atomic uint64 variable.
uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom)
Fetch and increment atomic uint64 variable.
uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom)
Load value of atomic uint64 variable.
void odp_barrier_init(odp_barrier_t *barr, int count)
Initialize barrier with thread count.
void odp_mb_full(void)
Full memory barrier.
void odp_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
#define ODP_ALIGNED_CACHE
Defines type/struct/variable to be cache line size aligned.
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.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
void odp_event_free(odp_event_t event)
Free event.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
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.
void odp_ticketlock_init(odp_ticketlock_t *tklock)
Initialize ticket lock.
void odp_ticketlock_lock(odp_ticketlock_t *tklock)
Acquire ticket lock.
void odp_ticketlock_unlock(odp_ticketlock_t *tklock)
Release ticket lock.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_TIMEOUT
Timeout pool.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_queue_type_t
Queue type.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
#define ODP_SCHED_SYNC_PARALLEL
Parallel scheduled queues.
int odp_schedule_group_t
Scheduler thread group.
int odp_schedule_group_join(odp_schedule_group_t group, const odp_thrmask_t *mask)
Join a schedule group.
#define ODP_SCHED_SYNC_ATOMIC
Atomic queue synchronization.
#define ODP_SCHED_SYNC_ORDERED
Ordered queue synchronization.
int odp_schedule_group_destroy(odp_schedule_group_t group)
Schedule group destroy.
int odp_schedule_group_leave(odp_schedule_group_t group, const odp_thrmask_t *mask)
Leave a schedule group.
#define ODP_SCHED_GROUP_INVALID
Invalid scheduler group.
#define ODP_SCHED_NO_WAIT
Do not wait.
int odp_schedule_default_prio(void)
Default scheduling priority level.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
odp_schedule_group_t odp_schedule_group_create(const char *name, const odp_thrmask_t *mask)
Schedule group create.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_SINGLE_VA
Single virtual address.
#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.
double odp_fract_u64_to_dbl(const odp_fract_u64_t *fract)
Convert fractional number (u64) to double.
void odp_sys_info_print(void)
Print system info.
void odp_thrmask_set(odp_thrmask_t *mask, int thr)
Add thread to mask.
int odp_thread_id(void)
Get thread identifier.
void odp_thrmask_zero(odp_thrmask_t *mask)
Clear entire thread mask.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
uint64_t odp_time_to_ns(odp_time_t time)
Convert time to nanoseconds.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
void odp_time_wait_ns(uint64_t ns)
Wait the specified number of nanoseconds.
odp_time_t odp_time_global(void)
Current global time.
odp_time_t odp_time_local(void)
Current local time.
uint64_t odp_time_global_strict_ns(void)
Current global time in nanoseconds (strict)
odp_time_t odp_time_global_strict(void)
Current global time (strict)
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
uint64_t odp_time_global_ns(void)
Current global time in nanoseconds.
uint64_t odp_timer_tick_to_ns(odp_timer_pool_t timer_pool, uint64_t ticks)
Convert timer ticks to nanoseconds.
int odp_timer_pool_start_multi(odp_timer_pool_t timer_pool[], int num)
Start timer pools.
void odp_timer_pool_print(odp_timer_pool_t timer_pool)
Print timer pool debug information.
odp_timeout_t odp_timeout_alloc(odp_pool_t pool)
Timeout alloc.
uint64_t odp_timeout_tick(odp_timeout_t tmo)
Timeout expiration tick.
int odp_timer_free(odp_timer_t timer)
Free a timer.
int odp_timer_periodic_start(odp_timer_t timer, const odp_timer_periodic_start_t *start_param)
Start a periodic timer.
odp_timeout_t odp_timeout_from_event(odp_event_t ev)
Get timeout handle from a ODP_EVENT_TIMEOUT type event.
#define ODP_TIMER_POOL_INVALID
Invalid timer pool handle.
int odp_timer_periodic_capability(odp_timer_clk_src_t clk_src, odp_timer_periodic_capability_t *capa)
Periodic timer capability.
odp_timer_pool_t odp_timer_pool_create(const char *name, const odp_timer_pool_param_t *params)
Create a timer pool.
int odp_timer_cancel(odp_timer_t timer, odp_event_t *tmo_ev)
Cancel a timer.
uint64_t odp_timer_current_tick(odp_timer_pool_t timer_pool)
Current tick value.
int odp_timer_capability(odp_timer_clk_src_t clk_src, odp_timer_capability_t *capa)
Query timer capabilities per clock source.
uint64_t odp_timer_ns_to_tick(odp_timer_pool_t timer_pool, uint64_t ns)
Convert nanoseconds to timer ticks.
int odp_timer_periodic_ack(odp_timer_t timer, odp_event_t tmo_ev)
Acknowledge timeout from a periodic timer.
odp_timer_clk_src_t
Clock sources for timer pools.
int odp_timer_start(odp_timer_t timer, const odp_timer_start_t *start_param)
Start a timer.
odp_timer_retval_t
Return values for timer start, restart and cancel calls.
int odp_timer_periodic_cancel(odp_timer_t timer)
Cancel a periodic timer.
odp_event_t odp_timeout_to_event(odp_timeout_t tmo)
Convert timeout handle to event handle.
#define ODP_TIMEOUT_INVALID
Invalid timeout handle.
odp_timer_t odp_timer_alloc(odp_timer_pool_t timer_pool, odp_queue_t queue, const void *user_ptr)
Allocate a timer.
#define ODP_CLOCK_DEFAULT
The default clock source.
#define ODP_TIMER_INVALID
Invalid timer handle.
void odp_timer_pool_param_init(odp_timer_pool_param_t *param)
Initialize timer pool parameters.
void odp_timer_pool_destroy(odp_timer_pool_t timer_pool)
Destroy a timer pool.
void * odp_timeout_user_ptr(odp_timeout_t tmo)
Return user pointer for the timeout.
@ ODP_TIMER_SUCCESS
Timer operation succeeded.
@ ODP_TIMER_TOO_NEAR
Timer operation failed, too near to the current time.
@ ODP_TIMER_FAIL
Timer operation failed.
@ ODP_TIMER_TYPE_PERIODIC
Periodic timer.
@ ODP_TIMER_TICK_REL
Relative ticks.
@ ODP_TIMER_TICK_ABS
Absolute ticks.
Unsigned 64 bit fractional number.
uint64_t integer
Integer part.
uint64_t denom
Denominator of the fraction part.
uint64_t numer
Numerator of the fraction part.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
odp_feature_t not_used
Unused features.
uint32_t num
Number of buffers in the pool.
struct odp_pool_param_t::@127 tmo
Parameters for timeout pools.
uint32_t cache_size
Maximum number of buffers cached locally per thread.
odp_pool_type_t type
Pool type.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
odp_fract_u64_t min_base_freq_hz
Minimum supported base frequency value.
uint32_t max_timers
Maximum number of single shot timers in a pool.
uint32_t max_pools
Maximum number of timer pools for single shot timers (per clock source)
odp_fract_u64_t max_base_freq_hz
Maximum supported base frequency value.
odp_timer_res_capability_t max_res
Maximum resolution.
struct odp_timer_capability_t::@156 periodic
Periodic timer capabilities.
Periodic timer capability.
odp_fract_u64_t base_freq_hz
Periodic timer pool base frequency in hertz.
uint64_t res_ns
Timeout resolution in nanoseconds.
uint64_t max_multiplier
Maximum base frequency multiplier.
Periodic timer start parameters.
odp_event_t tmo_ev
Timeout event.
uint64_t freq_multiplier
Base frequency multiplier.
uint64_t first_tick
First expiration time.
uint64_t res_ns
Timeout resolution in nanoseconds.
uint64_t res_hz
Timeout resolution in hertz.
odp_timer_type_t timer_type
Timer type.
uint64_t max_multiplier
Maximum base frequency multiplier.
odp_fract_u64_t base_freq_hz
Timer pool base frequency in hertz.
struct odp_timer_pool_param_t::@157 periodic
Periodic timer parameters.
uint64_t min_tmo
Minimum relative timeout in nanoseconds.
uint32_t num_timers
Number of timers in the pool.
odp_timer_clk_src_t clk_src
Clock source for timers.
uint64_t max_tmo
Maximum relative timeout in nanoseconds.
uint64_t res_hz
Timeout resolution in hertz.
uint64_t res_ns
Timeout resolution in nanoseconds.
uint64_t tick
Expiration time in ticks.
odp_event_t tmo_ev
Timeout event.
odp_timer_tick_type_t tick_type
Tick type.
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 cls
Classifier APIs, e.g., odp_cls_xxx(), odp_cos_xxx()
struct odp_feature_t::@148 feat
Individual feature bits.
uint32_t compress
Compression APIs, e.g., odp_comp_xxx()