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
40typedef 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;
110typedef struct test_log_t {
117typedef 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;
141static 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"
204static 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 if (sscanf(optarg,
"%" SCNu64
":%" SCNu64
":%" SCNu64
":%llu",
299 &test_opt->freq.integer, &test_opt->freq.numer,
300 &test_opt->freq.denom, &test_opt->max_multiplier) != 4) {
301 ODPH_ERR(
"Invalid periodic timer pool parameters\n");
306 test_opt->multiplier = strtoull(optarg, NULL, 0);
309 test_opt->output = 1;
310 if (strlen(optarg) >= MAX_FILENAME) {
311 ODPH_ERR(
"Filename too long\n");
314 odph_strcpy(test_opt->filename, optarg, MAX_FILENAME);
317 test_opt->early_retry = atoi(optarg);
320 test_opt->clk_src = atoi(optarg);
323 switch (atoi(optarg)) {
336 test_opt->num_queue = atoi(optarg);
339 test_opt->interval = atoi(optarg);
342 test_opt->max_diff = atoi(optarg);
345 test_opt->cancel = atoi(optarg);
348 test_opt->switch_event = atoi(optarg);
351 test_opt->switch_timer = atoi(optarg);
354 test_opt->cancel_start = atoi(optarg);
357 test_opt->exit_on_error = 1;
360 test_opt->groups = 1;
376 if (test_opt->mode == MODE_PERIODIC) {
377 if ((test_opt->freq.integer == 0 && test_opt->freq.numer == 0) ||
378 (test_opt->freq.numer != 0 && test_opt->freq.denom == 0)) {
379 ODPH_ERR(
"Bad frequency\n");
383 test_opt->period_ns =
386 if (test_opt->offset_ns == UINT64_MAX)
387 test_opt->offset_ns = 0;
389 if (test_opt->res_ns < 0) {
390 ODPH_ERR(
"Resolution (res_ns) must be >= 0 with single shot timer\n");
394 if (test_opt->offset_ns == UINT64_MAX)
397 if (test_opt->mode == MODE_CONCURRENCY)
398 test_opt->offset_ns = 0;
401 test_opt->warmup_timers = test_opt->num_warmup * test_opt->burst;
402 test_opt->tot_timers =
403 test_opt->warmup_timers + test_opt->num * test_opt->burst;
405 if (test_opt->mode == MODE_ONESHOT)
406 test_opt->alloc_timers = test_opt->tot_timers;
408 test_opt->alloc_timers = test_opt->burst;
416 uint64_t res_ns, res_hz;
417 uint64_t max_res_ns, max_res_hz;
418 uint64_t period_ns = test_global->opt.period_ns;
419 uint64_t num_tmo = test_global->opt.num + test_global->opt.num_warmup;
420 uint64_t offset_ns = test_global->opt.offset_ns;
421 enum mode_e mode = test_global->opt.mode;
427 if (test_global->opt.res_ns == 0 && test_global->opt.res_hz == 0) {
428 res_ns = test_global->opt.period_ns / 10;
430 }
else if (test_global->opt.res_ns) {
431 res_ns = test_global->opt.res_ns;
435 res_hz = test_global->opt.res_hz;
438 if (res_ns && res_ns < max_res_ns) {
439 ODPH_ERR(
"Resolution %" PRIu64
" nsec too high.\n"
440 "Highest resolution %" PRIu64
441 " nsec. Default resolution is period / 10.\n\n",
446 if (res_hz && res_hz > max_res_hz) {
447 ODPH_ERR(
"Resolution %" PRIu64
" hz too high.\n"
448 "Highest resolution %" PRIu64
449 " hz. Default resolution is period / 10.\n\n",
455 timer_param->
res_ns = res_ns;
457 timer_param->
res_hz = res_hz;
459 if (mode == MODE_ONESHOT) {
460 timer_param->
min_tmo = offset_ns / 2;
461 timer_param->
max_tmo = offset_ns + ((num_tmo + 1) * period_ns);
463 if (mode == MODE_RESTART_ABS)
464 timer_param->
min_tmo = period_ns / 10;
466 timer_param->
min_tmo = period_ns;
467 timer_param->
max_tmo = offset_ns + (2 * period_ns);
470 if (test_global->opt.max_tmo_ns) {
471 if (test_global->opt.max_tmo_ns < timer_param->
max_tmo) {
472 ODPH_ERR(
"Max tmo is too small. Must be at least %" PRIu64
" nsec.\n",
477 timer_param->
max_tmo = test_global->opt.max_tmo_ns;
480 printf(
" period: %" PRIu64
" nsec\n", period_ns);
481 printf(
" max res nsec: %" PRIu64
"\n", max_res_ns);
482 printf(
" max res hertz: %" PRIu64
"\n", max_res_hz);
484 test_global->period_dbl = period_ns;
495 double freq_dbl, min_freq, max_freq;
498 uint64_t res_hz = test_global->opt.res_hz;
499 uint64_t max_multiplier = test_global->opt.max_multiplier;
500 uint64_t multiplier = test_global->opt.multiplier;
505 res_ns = test_global->opt.res_ns;
513 ODPH_ERR(
"Resolution too high\n");
518 if (test_global->opt.res_ns < 0)
532 ODPH_ERR(
"Requested periodic timer capabilities are not supported.\n"
533 "Capabilities: min base freq %g Hz, max base freq %g Hz, "
534 "max res %" PRIu64
" Hz\n",
540 printf(
"Requested base frequency is not met. Using %.2f Hz instead of %.2f Hz.\n",
550 test_global->base_freq = freq;
559 timer_param->
res_hz = res_hz;
561 timer_param->
res_ns = res_ns;
563 printf(
" min freq capa: %.2f hz\n", min_freq);
564 printf(
" max freq capa: %.2f hz\n", max_freq);
565 printf(
" freq option: %.2f hz\n", opt_freq);
566 printf(
" freq: %.2f hz\n", freq_dbl);
567 printf(
" freq integer: %" PRIu64
"\n", freq.
integer);
568 printf(
" freq numer: %" PRIu64
"\n", freq.
numer);
569 printf(
" freq denom: %" PRIu64
"\n", freq.
denom);
570 printf(
" max_multiplier: %" PRIu64
"\n", max_multiplier);
571 printf(
" multiplier: %" PRIu64
"\n", multiplier);
572 printf(
" timer freq: %.2f hz\n", multiplier * freq_dbl);
573 printf(
" timer period: %.2f nsec\n", test_global->period_dbl);
574 printf(
" resolution capa: %" PRIu64
" nsec\n", capa.
res_ns);
579static int create_timers(test_global_t *test_global)
595 uint64_t i, num_tmo, num_warmup, burst, burst_gap;
596 uint64_t tot_timers, alloc_timers;
601 mode = test_global->opt.mode;
602 alloc_timers = test_global->opt.alloc_timers;
603 tot_timers = test_global->opt.tot_timers;
604 num_warmup = test_global->opt.num_warmup;
605 num_tmo = num_warmup + test_global->opt.num;
606 burst = test_global->opt.burst;
607 burst_gap = test_global->opt.burst_gap;
608 offset_ns = test_global->opt.offset_ns;
609 queue = test_global->queue;
610 group = test_global->group;
616 for (i = 0; i < alloc_timers; i++) {
621 if (test_global->opt.groups) {
628 for (i = 0; i < (uint64_t)test_global->opt.cpu_count; i++) {
632 ODPH_ERR(
"Group create failed.\n");
641 queue_param.
sched.
sync = test_global->opt.queue_type;
644 for (i = 0; i < (uint64_t)test_global->opt.num_queue; i++) {
645 if (test_global->opt.groups)
646 queue_param.
sched.
group = group[i % test_global->opt.cpu_count];
650 ODPH_ERR(
"Queue create failed.\n");
657 pool_param.
tmo.
num = alloc_timers + pool_param.
tmo.
cache_size * test_global->opt.cpu_count;
658 if (mode == MODE_CONCURRENCY)
659 pool_param.
tmo.
num += test_global->opt.cpu_count;
664 ODPH_ERR(
"Timeout pool create failed.\n");
668 test_global->timeout_pool = pool;
669 clk_src = test_global->opt.clk_src;
672 ODPH_ERR(
"Timer capa failed\n");
678 if (mode == MODE_PERIODIC) {
680 ODPH_ERR(
"Periodic timers not supported "
681 "(ODP_TIMER_TYPE_PERIODIC_BASE_MUL).\n");
687 printf(
"\nTest parameters:\n");
688 printf(
" clock source: %i\n", clk_src);
689 printf(
" max timers capa: %" PRIu32
"\n", max_timers);
690 printf(
" mode: %i\n", mode);
691 printf(
" queue type: %i\n", test_global->opt.queue_type);
692 printf(
" num queue: %i\n", test_global->opt.num_queue);
693 printf(
" sched groups: %s\n", test_global->opt.groups ?
"yes" :
"no");
697 if (mode == MODE_PERIODIC)
698 ret = periodic_params(test_global, &timer_param, &timer_capa);
700 ret = single_shot_params(test_global, &timer_param, &timer_capa);
706 test_global->res_ns = 1000000000.0 / timer_param.
res_hz;
707 printf(
" resolution: %" PRIu64
" Hz\n", timer_param.
res_hz);
709 test_global->res_ns = timer_param.
res_ns;
710 printf(
" resolution: %" PRIu64
" nsec\n", timer_param.
res_ns);
714 if (mode == MODE_CONCURRENCY)
715 timer_param.
num_timers += test_global->opt.cpu_count;
717 if (max_timers && timer_param.
num_timers > max_timers) {
718 ODPH_ERR(
"Too many timers: %" PRIu64
" (max %u)\n", test_global->opt.alloc_timers,
725 printf(
" restart retries: %i\n", test_global->opt.early_retry);
726 if (test_global->opt.output)
727 printf(
" log file: %s\n", test_global->opt.filename);
728 printf(
" start offset: %" PRIu64
" nsec\n", offset_ns);
729 printf(
" min timeout: %" PRIu64
" nsec\n", timer_param.
min_tmo);
730 printf(
" max timeout: %" PRIu64
" nsec\n", timer_param.
max_tmo);
731 printf(
" num timeout: %" PRIu64
"\n", num_tmo);
732 printf(
" num warmup: %" PRIu64
"\n", num_warmup);
733 printf(
" burst size: %" PRIu64
"\n", burst);
734 printf(
" burst gap: %" PRIu64
"\n", burst_gap);
735 printf(
" total timers: %" PRIu64
"\n", tot_timers);
736 printf(
" warmup timers: %" PRIu64
"\n", test_global->opt.warmup_timers);
737 printf(
" alloc timers: %" PRIu64
"\n", alloc_timers);
738 printf(
" warmup time: %.2f sec\n",
739 (offset_ns + (num_warmup * test_global->period_dbl)) / 1000000000.0);
740 printf(
" test run time: %.2f sec\n\n",
741 (offset_ns + (num_tmo * test_global->period_dbl)) / 1000000000.0);
746 ODPH_ERR(
"Timer pool create failed\n");
751 ODPH_ERR(
"Timer pool start failed\n");
760 test_global->timer_pool = timer_pool;
762 if (mode == MODE_PERIODIC) {
767 for (i = 0; i < alloc_timers; i++) {
768 q = queue[i % test_global->opt.num_queue];
769 timer_ctx_t *ctx = &test_global->timer_ctx[i];
771 if (mode == MODE_PERIODIC) {
779 ODPH_ERR(
"Timeout alloc failed\n");
788 ODPH_ERR(
"Timer alloc failed.\n");
797 for (i = 0; i < 1000; i++) {
801 ODPH_ERR(
"Spurious event received\n");
810static int start_timers(test_global_t *test_global)
814 uint64_t period_ns, start_ns, nsec, offset_ns;
816 uint64_t i, j, idx, num_tmo, num_warmup, burst, burst_gap;
819 mode = test_global->opt.mode;
820 num_warmup = test_global->opt.num_warmup;
821 num_tmo = num_warmup + test_global->opt.num;
822 burst = test_global->opt.burst;
823 burst_gap = test_global->opt.burst_gap;
824 period_ns = test_global->opt.period_ns;
825 offset_ns = test_global->opt.offset_ns;
826 timer_pool = test_global->timer_pool;
837 test_global->start_tick = start_tick;
838 test_global->start_ns = start_ns;
842 if (mode != MODE_ONESHOT)
845 for (i = 0; i < num_tmo; i++) {
848 for (j = 0; j < burst; j++) {
849 timer_ctx_t *ctx = &test_global->timer_ctx[idx];
852 if (mode == MODE_PERIODIC) {
855 nsec = offset_ns + (j * burst_gap);
859 ctx->nsec = start_ns + test_global->period_dbl + 0.5;
861 ctx->nsec = start_ns + nsec;
863 ctx->first_period = start_tick +
865 test_global->period_dbl + 0.5);
871 }
else if (mode == MODE_CONCURRENCY) {
872 ctx->nsec = start_ns + test_global->opt.period_ns;
874 start_param.
tick = test_global->period_tick;
875 start_param.
tmo_ev = ctx->event;
879 nsec = offset_ns + (i * period_ns) + (j * burst_gap);
880 ctx->nsec = start_ns + nsec;
884 start_param.
tmo_ev = ctx->event;
889 ODPH_ERR(
"Timer[%" PRIu64
"] set failed: %i\n", idx, retval);
902static int destroy_timers(test_global_t *test_global)
904 uint64_t i, alloc_timers;
908 alloc_timers = test_global->opt.alloc_timers;
910 for (i = 0; i < alloc_timers; i++) {
911 timer = test_global->timer_ctx[i].timer;
917 ODPH_ERR(
"Timer free failed: %" PRIu64
"\n", i);
927 ODPH_ERR(
"Pool destroy failed.\n");
932 for (i = 0; i < (uint64_t)test_global->opt.num_queue; i++) {
934 ODPH_ERR(
"Queue destroy failed.\n");
939 if (test_global->opt.groups) {
940 for (i = 0; i < (uint64_t)test_global->opt.cpu_count; i++) {
942 ODPH_ERR(
"Group destroy failed.\n");
951static void print_nsec_error(
const char *str, int64_t nsec,
double res_ns,
954 printf(
" %s: %12" PRIi64
" / %.3fx resolution",
955 str, nsec, (
double)nsec / res_ns);
957 printf(
", thread %d", tid);
959 printf(
", event %d", idx);
963static int print_stat(test_global_t *test_global)
965 test_stat_t test_stat;
966 test_stat_t *stat = &test_stat;
968 test_stat_t *s = test_global->stat;
969 test_log_t *log = test_global->log;
970 double res_ns = test_global->res_ns;
971 uint64_t ave_after = 0;
972 uint64_t ave_before = 0;
973 uint64_t nsec_before_min_tid = 0;
974 uint64_t nsec_before_max_tid = 0;
975 uint64_t nsec_after_min_tid = 0;
976 uint64_t nsec_after_max_tid = 0;
978 memset(stat, 0,
sizeof(*stat));
979 stat->nsec_before_min = UINT64_MAX;
980 stat->nsec_after_min = UINT64_MAX;
982 for (
int i = 1; i < test_global->opt.cpu_count + 1; i++) {
983 stat->nsec_before_sum += s[i].nsec_before_sum;
984 stat->nsec_after_sum += s[i].nsec_after_sum;
985 stat->num_before += s[i].num_before;
986 stat->num_exact += s[i].num_exact;
987 stat->num_after += s[i].num_after;
988 stat->num_retry += s[i].num_retry;
990 if (s[i].nsec_before_min < stat->nsec_before_min) {
991 stat->nsec_before_min = s[i].nsec_before_min;
992 stat->nsec_before_min_idx = s[i].nsec_before_min_idx;
993 nsec_before_min_tid = i;
996 if (s[i].nsec_after_min < stat->nsec_after_min) {
997 stat->nsec_after_min = s[i].nsec_after_min;
998 stat->nsec_after_min_idx = s[i].nsec_after_min_idx;
999 nsec_after_min_tid = i;
1002 if (s[i].nsec_before_max > stat->nsec_before_max) {
1003 stat->nsec_before_max = s[i].nsec_before_max;
1004 stat->nsec_before_max_idx = s[i].nsec_before_max_idx;
1005 nsec_before_max_tid = i;
1008 if (s[i].nsec_after_max > stat->nsec_after_max) {
1009 stat->nsec_after_max = s[i].nsec_after_max;
1010 stat->nsec_after_max_idx = s[i].nsec_after_max_idx;
1011 nsec_after_max_tid = i;
1015 if (stat->num_after)
1016 ave_after = stat->nsec_after_sum / stat->num_after;
1018 stat->nsec_after_min = 0;
1020 if (stat->num_before)
1021 ave_before = stat->nsec_before_sum / stat->num_before;
1023 stat->nsec_before_min = 0;
1025 tot_timers = stat->num_before + stat->num_after + stat->num_exact;
1028 FILE *file = test_global->file;
1030 fprintf(file,
" Timer thread tmo(ns) diff(ns)\n");
1032 for (uint64_t i = 0; i < tot_timers; i++) {
1033 fprintf(file,
"%8" PRIu64
" %7u %12" PRIu64
" %10"
1034 PRIi64
"\n", i, log[i].tid, log[i].tmo_ns, log[i].diff_ns);
1037 fprintf(file,
"\n");
1040 printf(
"\nTest results:\n");
1041 printf(
" num after: %12" PRIu64
" / %.2f%%\n",
1042 stat->num_after, 100.0 * stat->num_after / tot_timers);
1043 printf(
" num before: %12" PRIu64
" / %.2f%%\n",
1044 stat->num_before, 100.0 * stat->num_before / tot_timers);
1045 printf(
" num exact: %12" PRIu64
" / %.2f%%\n",
1046 stat->num_exact, 100.0 * stat->num_exact / tot_timers);
1047 printf(
" num retry: %12" PRIu64
" / %.2f%%\n",
1048 stat->num_retry, 100.0 * stat->num_retry / tot_timers);
1049 printf(
" error after (nsec):\n");
1050 print_nsec_error(
"min", stat->nsec_after_min, res_ns, nsec_after_min_tid,
1051 stat->nsec_after_min_idx);
1052 print_nsec_error(
"max", stat->nsec_after_max, res_ns, nsec_after_max_tid,
1053 stat->nsec_after_max_idx);
1054 print_nsec_error(
"ave", ave_after, res_ns, -1, -1);
1055 printf(
" error before (nsec):\n");
1056 print_nsec_error(
"min", stat->nsec_before_min, res_ns, nsec_before_min_tid,
1057 stat->nsec_before_min_idx);
1058 print_nsec_error(
"max", stat->nsec_before_max, res_ns, nsec_before_max_tid,
1059 stat->nsec_before_max_idx);
1060 print_nsec_error(
"ave", ave_before, res_ns, -1, -1);
1062 if (test_global->opt.mode == MODE_PERIODIC && !test_global->opt.offset_ns) {
1066 for (
int i = 0; i < (int)test_global->opt.alloc_timers; i++) {
1067 timer_ctx_t *t = &test_global->timer_ctx[i];
1068 int64_t v = t->first_tmo_diff;
1070 if (ODPH_ABS(v) > ODPH_ABS(max)) {
1076 printf(
" first timeout difference to one period, based on %s (nsec):\n",
1077 test_global->timer_ctx[idx].tmo_tick ?
"timeout tick" :
"time");
1078 print_nsec_error(
"max", max, res_ns, -1, -1);
1083 for (
int i = 0; i < (int)test_global->opt.alloc_timers; i++) {
1084 timer_ctx_t *t = &test_global->timer_ctx[i];
1085 int64_t v = t->nsec_final;
1087 if (ODPH_ABS(v) > ODPH_ABS(max))
1091 printf(
" final timeout error (nsec):\n");
1092 print_nsec_error(
"max", max, res_ns, -1, -1);
1096 if (test_global->common_options.is_export) {
1097 if (test_common_write(
"num after,num before,num exact,num retry,"
1098 "error after min (nsec),error after min resolution,"
1099 "error after max (nsec),error after max resolution,"
1100 "error after ave (nsec),error after ave resolution,"
1101 "error before min (nsec),error before min resolution,"
1102 "error before max (nsec),error before max resolution,"
1103 "error before ave (nsec),error before ave resolution,"
1104 "final timeout error max (nsec),"
1105 "final timeout error max resolution\n")) {
1106 ODPH_ERR(
"Export failed\n");
1107 test_common_write_term();
1111 if (test_common_write(
"%" PRIu64
",%" PRIu64
",%" PRIu64
",%" PRIu64
",%" PRIu64
","
1112 "%f,%" PRIu64
",%f,%" PRIu64
",%f,%" PRIu64
",%f,%" PRIu64
","
1113 "%f,%" PRIu64
",%f,%" PRId64
",%f\n",
1114 stat->num_after, stat->num_before,
1115 stat->num_exact, stat->num_retry,
1116 stat->nsec_after_min, (
double)stat->nsec_after_min / res_ns,
1117 stat->nsec_after_max, (
double)stat->nsec_after_max / res_ns,
1118 ave_after, (
double)ave_after / res_ns,
1119 stat->nsec_before_min, (
double)stat->nsec_before_min / res_ns,
1120 stat->nsec_before_max, (
double)stat->nsec_before_max / res_ns,
1121 ave_before, (
double)ave_before / res_ns,
1122 max, (
double)max / res_ns
1124 ODPH_ERR(
"Export failed\n");
1125 test_common_write_term();
1129 test_common_write_term();
1135static void cancel_periodic_timers(test_global_t *test_global)
1137 uint64_t i, alloc_timers;
1140 alloc_timers = test_global->opt.alloc_timers;
1142 for (i = 0; i < alloc_timers; i++) {
1143 timer = test_global->timer_ctx[i].timer;
1149 ODPH_ERR(
"Failed to cancel periodic timer.\n");
1153static void process_event_concurrency(uint64_t events, test_global_t *test_global, timer_ctx_t *ctx,
1160 const uint64_t period_ns = test_global->opt.period_ns;
1161 const uint64_t tick = test_global->period_tick;
1162 const int cancel_start =
1163 test_global->opt.cancel_start && !(events % test_global->opt.cancel_start);
1164 const int cancel = test_global->opt.cancel && !(events % test_global->opt.cancel);
1165 const int switch_timer =
1166 test_global->opt.switch_timer && !(events % test_global->opt.switch_timer);
1167 const int switch_event =
1168 test_global->opt.switch_event && !(events % test_global->opt.switch_event);
1181 ctx->nsec = time_ns + period_ns;
1194 "odp_timer_cancel() succeeded: event %p ctx %p sched event %p sched ctx %p\n",
1195 event, ev_ctx, ev, ctx);
1206 test_global->queue[events % test_global->opt.num_queue],
1209 ODPH_ERR(
"odp_timer_alloc() failed\n");
1213 ODPH_ERR(
"odp_timer_free()\n");
1227 ODPH_ERR(
"odp_timeout_alloc() failed\n");
1236 start_param.
tick = tick;
1241 ODPH_ERR(
"odp_timer_start(): %d\n", ret);
1253 ODPH_ERR(
"odp_timeout_alloc() failed\n");
1261 ODPH_ERR(
"odp_timer_start(): %d\n", ret);
1279static int run_test(
void *arg)
1281 test_global_t *test_global = (test_global_t *)arg;
1284 uint64_t time_ns, diff_ns;
1291 test_log_t *log = test_global->log;
1292 enum mode_e mode = test_global->opt.mode;
1293 uint64_t tot_timers = test_global->opt.tot_timers;
1294 double period_dbl = test_global->period_dbl;
1298 if (tid > test_global->opt.cpu_count) {
1299 ODPH_ERR(
"tid %d is larger than cpu_count %d.\n", tid, test_global->opt.cpu_count);
1303 test_stat_t *stat = &test_global->stat[tid];
1305 memset(stat, 0,
sizeof(*stat));
1306 stat->nsec_before_min = UINT64_MAX;
1307 stat->nsec_after_min = UINT64_MAX;
1309 if (test_global->opt.groups) {
1312 group = test_global->group[tid - 1];
1315 ODPH_ERR(
"odp_schedule_group_join() failed\n");
1327 if (mode == MODE_PERIODIC) {
1329 test_global->opt.alloc_timers)
1344 if (mode == MODE_PERIODIC) {
1345 if (!ctx->events && !test_global->opt.offset_ns) {
1360 ctx->first_tmo_diff =
1363 tmo_ns += ctx->first_tmo_diff;
1369 ctx->first_tmo_diff = (int64_t)time_ns - (int64_t)tmo_ns;
1370 tmo_ns = ctx->nsec = time_ns;
1377 tmo_ns += ctx->events * period_dbl + 0.5;
1379 }
else if (mode == MODE_CONCURRENCY) {
1380 uint64_t events = ++ctx->events;
1381 uint64_t starts = ctx->starts;
1383 if (events > starts) {
1384 ODPH_ERR(
"ctx %p timer %p time %" PRIu64
" starts %" PRIu64
1385 " events %" PRIu64
"\n",
1386 ctx, ctx->timer, time_ns, starts, events);
1387 if (test_global->opt.exit_on_error)
1391 int64_t diff = (int64_t)time_ns - (int64_t)tmo_ns;
1393 if (test_global->opt.max_diff &&
1394 diff > (int64_t)test_global->opt.max_diff) {
1395 ODPH_ERR(
"ctx %p timer %p time %" PRIu64
" diff %" PRIi64
"\n", ctx,
1396 ctx->timer, time_ns, diff);
1397 if (test_global->opt.exit_on_error)
1404 if (events >= test_global->opt.warmup_timers && events < tot_timers) {
1405 uint64_t i = events - test_global->opt.warmup_timers;
1407 ctx->nsec_final = (int64_t)time_ns - (int64_t)tmo_ns;
1410 log[i].tmo_ns = tmo_ns;
1414 if (time_ns > tmo_ns) {
1415 diff_ns = time_ns - tmo_ns;
1417 stat->nsec_after_sum += diff_ns;
1418 if (diff_ns < stat->nsec_after_min) {
1419 stat->nsec_after_min = diff_ns;
1420 stat->nsec_after_min_idx = i;
1422 if (diff_ns > stat->nsec_after_max) {
1423 stat->nsec_after_max = diff_ns;
1424 stat->nsec_after_max_idx = i;
1427 log[i].diff_ns = diff_ns;
1429 }
else if (time_ns < tmo_ns) {
1430 diff_ns = tmo_ns - time_ns;
1432 stat->nsec_before_sum += diff_ns;
1433 if (diff_ns < stat->nsec_before_min) {
1434 stat->nsec_before_min = diff_ns;
1435 stat->nsec_before_min_idx = i;
1437 if (diff_ns > stat->nsec_before_max) {
1438 stat->nsec_before_max = diff_ns;
1439 stat->nsec_before_max_idx = i;
1442 log[i].diff_ns = -diff_ns;
1448 if ((mode == MODE_RESTART_ABS || mode == MODE_RESTART_REL) &&
1449 events < tot_timers - 1) {
1452 uint64_t nsec, tick;
1455 unsigned int retries = test_global->opt.early_retry;
1456 uint64_t start_ns = test_global->start_ns;
1457 uint64_t period_ns = test_global->opt.period_ns;
1464 for (j = 0; j < retries + 1; j++) {
1465 if (mode == MODE_RESTART_ABS) {
1467 ctx->nsec += period_ns;
1468 nsec = ctx->nsec - start_ns;
1469 tick = test_global->start_tick +
1474 tick = test_global->period_tick;
1477 ctx->nsec = time_ns + period_ns;
1482 start_param.
tick = tick;
1486 if (events >= test_global->opt.warmup_timers)
1494 ODPH_ERR(
"Timer set failed: %i. Timeout nsec "
1499 }
else if (mode == MODE_PERIODIC) {
1503 ODPH_ABORT(
"Failed to ack a periodic timer.\n");
1507 }
else if (mode == MODE_CONCURRENCY && events < tot_timers - 1) {
1508 process_event_concurrency(events, test_global, ctx, time_ns, ev);
1514 if (test_global->opt.groups) {
1516 ODPH_ERR(
"odp_schedule_group_leave() failed\n");
1522static void interval_loop_concurrency(test_global_t *test_global)
1524 uint64_t events_prev = 0;
1525 uint64_t events = 0;
1527 uint64_t prev_ns = start_ns;
1529 while (events < test_global->opt.tot_timers) {
1537 uint64_t e = events - events_prev;
1539 printf(
"sec %" PRIu64
" total events %" PRIu64
" events %" PRIu64
1540 " events/s %" PRIu64
"\n", sec_total, events, e, e * 1000 / msec);
1541 events_prev = events;
1546int main(
int argc,
char *argv[])
1550 test_opt_t test_opt;
1551 test_global_t *test_global;
1552 odph_helper_options_t helper_options;
1553 test_common_options_t common_options;
1558 argc = odph_parse_options(argc, argv);
1559 if (odph_options(&helper_options)) {
1560 ODPH_ERR(
"Reading ODP helper options failed.\n");
1564 argc = test_common_parse_options(argc, argv);
1565 if (test_common_options(&common_options)) {
1566 ODPH_ERR(
"Reading test options failed\n");
1570 if (parse_options(argc, argv, &test_opt))
1581 init.
mem_model = helper_options.mem_model;
1588 ODPH_ERR(
"Global init failed.\n");
1594 ODPH_ERR(
"Local init failed.\n");
1604 uint64_t size =
sizeof(test_global_t);
1610 ODPH_ERR(
"Shm alloc failed.\n");
1615 memset(test_global, 0, size);
1616 memcpy(&test_global->opt, &test_opt,
sizeof(test_opt_t));
1618 test_global->common_options = common_options;
1620 size = test_global->opt.alloc_timers *
sizeof(timer_ctx_t);
1625 ODPH_ERR(
"Timer context alloc failed.\n");
1631 memset(test_global->timer_ctx, 0, size);
1633 if (test_global->opt.output) {
1634 test_global->file = fopen(test_global->opt.filename,
"w");
1635 if (test_global->file == NULL) {
1636 ODPH_ERR(
"Failed to open output file %s: %s\n", test_global->opt.filename,
1642 size = (test_global->opt.tot_timers - test_global->opt.warmup_timers) *
1644 shm_log =
odp_shm_reserve(
"timer_accuracy_log", size,
sizeof(test_log_t),
1648 ODPH_ERR(
"Test log alloc failed.\n");
1654 memset(test_global->log, 0, size);
1657 odph_thread_t thread_tbl[MAX_WORKERS];
1661 odph_thread_common_param_t thr_common;
1662 odph_thread_param_t thr_param;
1664 memset(thread_tbl, 0,
sizeof(thread_tbl));
1666 num_workers = MAX_WORKERS;
1667 if (test_global->opt.cpu_count && test_global->opt.cpu_count < MAX_WORKERS)
1668 num_workers = test_global->opt.cpu_count;
1670 test_global->opt.cpu_count = num_workers;
1673 printf(
"num worker threads: %i\n", num_workers);
1675 printf(
"cpu mask: %s\n", cpumaskstr);
1677 ret = create_timers(test_global);
1685 odph_thread_param_init(&thr_param);
1686 thr_param.start = run_test;
1687 thr_param.arg = (
void *)test_global;
1690 odph_thread_common_param_init(&thr_common);
1691 thr_common.instance = instance;
1692 thr_common.cpumask = &cpumask;
1693 thr_common.share_param = 1;
1695 odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers);
1698 ret = start_timers(test_global);
1702 if (test_global->opt.mode == MODE_PERIODIC) {
1706 cancel_periodic_timers(test_global);
1707 }
else if (test_global->opt.mode == MODE_CONCURRENCY) {
1708 interval_loop_concurrency(test_global);
1711 odph_thread_join(thread_tbl, num_workers);
1713 ret = print_stat(test_global);
1718 if (test_global->file)
1719 fclose(test_global->file);
1721 if (destroy_timers(test_global))
1734 ODPH_ERR(
"Term local failed.\n");
1739 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.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_SINGLE_VA
Single virtual 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.
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_timeout_user_ptr(odp_timeout_t tmo)
Return user pointer for the timeout.
odp_timer_t odp_timer_periodic_alloc(odp_timer_pool_t timer_pool, const odp_timer_periodic_param_t *params)
Allocate a periodic timer.
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 an 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.
void odp_timer_periodic_param_init(odp_timer_periodic_param_t *param)
Initialize periodic timer parameters.
int odp_timer_cancel(odp_timer_t timer, odp_event_t *tmo_ev)
Cancel a single shot 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 single shot 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 single shot 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.
@ ODP_TIMER_BUSY
Timer operation failed, resources temporarily busy.
@ 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_BASE_MUL
Periodic timer, period defined through pool base frequency and a multiplier.
@ 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.
uint32_t cache_size
Maximum number of buffers cached locally per thread.
odp_pool_type_t type
Pool type.
struct odp_pool_param_t::@140 tmo
Parameters for timeout pools.
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.
struct odp_timer_capability_t::@186 periodic
Periodic timer capabilities.
uint32_t max_timers
Maximum number of single shot timers in a pool.
struct odp_timer_capability_t::@186::@187 support
Supported period configuration types.
odp_fract_u64_t max_base_freq_hz
Maximum supported base frequency value.
odp_timer_res_capability_t max_res
Maximum resolution.
uint32_t base_mul
ODP_TIMER_TYPE_PERIODIC_BASE_MUL supported.
Periodic timer capability.
struct odp_timer_periodic_capability_t::@182::@184 base_mul
Capability for ODP_TIMER_TYPE_PERIODIC_BASE_MUL.
odp_fract_u64_t base_freq_hz
Periodic timer pool base frequency in hertz.
uint64_t res_ns
Timeout resolution in nanoseconds.
odp_timer_type_t type
Periodic timer type for which to check the frequency support.
uint64_t max_multiplier
Maximum base frequency multiplier.
Periodic timer parameters.
const void * user_ptr
User pointer.
struct odp_timer_periodic_param_t::@191 base_mul
Parameters for ODP_TIMER_TYPE_PERIODIC_BASE_MUL timers.
odp_queue_t queue
Destination queue.
uint64_t multiplier
Base frequency multiplier.
Periodic timer start parameters.
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.
struct odp_timer_pool_param_t::@188 periodic
Periodic timer pool parameters.
odp_fract_u64_t base_freq_hz
Timer pool base frequency in hertz.
uint64_t min_tmo
Minimum relative timeout in nanoseconds.
uint32_t num_timers
Number of timers in the pool.
struct odp_timer_pool_param_t::@188::@189 base_mul
Pool parameters for ODP_TIMER_TYPE_PERIODIC_BASE_MUL.
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::@174 feat
Individual feature bits.
uint32_t compress
Compression APIs, e.g., odp_comp_xxx()