This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, master has been updated via 4a2588b84a28424ce9c9a31c971a0d8678a0c066 (commit) via 448100358c09d61f3fd8d137454b6bc45396a233 (commit) via 1b103ac26cf40df3c091c344418881c6013669da (commit) via a6241a89c18dd7a4a14214a100369f5ef46f25ef (commit) via 11bd13b261d291fd5b169e4a02c21d217fbf70ac (commit) from 5ee1d8235638278fca00589fd577860ce88450e6 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 4a2588b84a28424ce9c9a31c971a0d8678a0c066 Author: Petri Savolainen petri.savolainen@nokia.com Date: Tue Nov 26 10:12:01 2019 +0200
example: timer_accur: add option to retry on too early error
When running test in restart timer mode with a short period, some timer set calls may return ODP_TIMER_TOOEARLY errors e.g. due to delays from operating system interruptions. This happens especially with absolute expiration time.
Added -e option to specify how many times a timer restart is retried when expiration time too early error is returned.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com
diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c index 94adfb20b..03439d172 100644 --- a/example/timer/odp_timer_accuracy.c +++ b/example/timer/odp_timer_accuracy.c @@ -37,6 +37,8 @@ typedef struct { uint64_t num_exact; uint64_t num_after;
+ uint64_t num_tooearly; + } test_stat_t;
typedef struct test_log_t { @@ -55,6 +57,7 @@ typedef struct test_global_t { int mode; int init; int output; + int early_retry; } opt;
test_stat_t stat; @@ -91,6 +94,8 @@ static void print_usage(void) " 1: Set first burst of timers at init. Restart timers during test with absolute time.\n" " 2: Set first burst of timers at init. Restart timers during test with relative time.\n" " -o, --output <file> Output file for measurement logs\n" + " -e, --early_retry <num> When timer restart fails due to ODP_TIMER_TOOEARLY, retry this many times\n" + " with expiration time incremented by the period. Default: 0\n" " -i, --init Set global init parameters. Default: init params not set.\n" " -h, --help Display help and exit.\n\n"); } @@ -99,18 +104,19 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) { int opt, long_index; const struct option longopts[] = { - {"period", required_argument, NULL, 'p'}, - {"resolution", required_argument, NULL, 'r'}, - {"first", required_argument, NULL, 'f'}, - {"num", required_argument, NULL, 'n'}, - {"burst", required_argument, NULL, 'b'}, - {"mode", required_argument, NULL, 'm'}, - {"output", required_argument, NULL, 'o'}, - {"init", no_argument, NULL, 'i'}, - {"help", no_argument, NULL, 'h'}, + {"period", required_argument, NULL, 'p'}, + {"resolution", required_argument, NULL, 'r'}, + {"first", required_argument, NULL, 'f'}, + {"num", required_argument, NULL, 'n'}, + {"burst", required_argument, NULL, 'b'}, + {"mode", required_argument, NULL, 'm'}, + {"output", required_argument, NULL, 'o'}, + {"early_retry", required_argument, NULL, 'e'}, + {"init", no_argument, NULL, 'i'}, + {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; - const char *shortopts = "+p:r:f:n:b:m:o:ih"; + const char *shortopts = "+p:r:f:n:b:m:o:e:ih"; int ret = 0;
test_global->opt.period_ns = 200 * ODP_TIME_MSEC_IN_NS; @@ -121,6 +127,7 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) test_global->opt.mode = 0; test_global->opt.init = 0; test_global->opt.output = 0; + test_global->opt.early_retry = 0;
while (1) { opt = getopt_long(argc, argv, shortopts, longopts, &long_index); @@ -152,6 +159,9 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) /* filename is NULL terminated in anycase */ strncpy(test_global->filename, optarg, MAX_FILENAME); break; + case 'e': + test_global->opt.early_retry = atoi(optarg); + break; case 'i': test_global->opt.init = 1; break; @@ -285,6 +295,7 @@ static int start_timers(test_global_t *test_global) printf(" resolution capa: %" PRIu64 " nsec\n", res_capa); printf(" max timers capa: %" PRIu32 "\n", timer_capa.max_timers); printf(" mode: %i\n", mode); + printf(" restart retries: %i\n", test_global->opt.early_retry); if (test_global->opt.output) printf(" log file: %s\n", test_global->filename); printf(" start offset: %" PRIu64 " nsec\n", offset_ns); @@ -465,6 +476,8 @@ static void print_stat(test_global_t *test_global) stat->num_before, 100.0 * stat->num_before / tot_timers); printf(" num exact: %12" PRIu64 " / %.2f%%\n", stat->num_exact, 100.0 * stat->num_exact / tot_timers); + printf(" num retry: %12" PRIu64 " / %.2f%%\n", + stat->num_tooearly, 100.0 * stat->num_tooearly / tot_timers); printf(" error after (nsec):\n"); printf(" min: %12" PRIu64 " / %.3fx resolution\n", stat->nsec_after_min, (double)stat->nsec_after_min / res_ns); @@ -543,29 +556,41 @@ static void run_test(test_global_t *test_global)
if (mode && next_tmo < num_tmo) { /* Reset timer for next period */ - odp_timer_t timer; + odp_timer_t tim; uint64_t nsec, tick; odp_timer_set_t ret; - odp_timer_pool_t timer_pool = test_global->timer_pool; - - timer = ctx->timer; - - if (mode == 1) { - /* Absolute time */ - ctx->nsec += period_ns; - nsec = ctx->nsec - test_global->start_ns; - tick = test_global->start_tick + - odp_timer_ns_to_tick(timer_pool, nsec); - - ret = odp_timer_set_abs(timer, tick, &ev); - } else { - /* Relative time */ - tick = test_global->period_tick; - time = odp_time_local(); - time_ns = odp_time_to_ns(time); - ctx->nsec = time_ns + period_ns; - - ret = odp_timer_set_rel(timer, tick, &ev); + unsigned int j; + odp_timer_pool_t tp = test_global->timer_pool; + unsigned int retries = test_global->opt.early_retry; + uint64_t start_ns = test_global->start_ns; + + tim = ctx->timer; + + /* Depending on the option, retry when expiration + * time is too early */ + for (j = 0; j < retries + 1; j++) { + if (mode == 1) { + /* Absolute time */ + ctx->nsec += period_ns; + nsec = ctx->nsec - start_ns; + tick = test_global->start_tick + + odp_timer_ns_to_tick(tp, nsec); + + ret = odp_timer_set_abs(tim, tick, &ev); + } else { + /* Relative time */ + tick = test_global->period_tick; + time = odp_time_local(); + time_ns = odp_time_to_ns(time); + ctx->nsec = time_ns + period_ns; + + ret = odp_timer_set_rel(tim, tick, &ev); + } + + if (ret == ODP_TIMER_TOOEARLY) + stat->num_tooearly++; + else + break; }
if (ret != ODP_TIMER_SUCCESS) {
commit 448100358c09d61f3fd8d137454b6bc45396a233 Author: Petri Savolainen petri.savolainen@nokia.com Date: Fri Nov 22 15:33:31 2019 +0200
example: timer_accur: add output file option
Added optio to output measurement samples into a log file.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com
diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c index 36827ad59..94adfb20b 100644 --- a/example/timer/odp_timer_accuracy.c +++ b/example/timer/odp_timer_accuracy.c @@ -15,6 +15,8 @@
#include <odp_api.h>
+#define MAX_FILENAME 128 + typedef struct timer_ctx_t { odp_timer_t timer; odp_event_t event; @@ -37,6 +39,12 @@ typedef struct {
} test_stat_t;
+typedef struct test_log_t { + uint64_t tmo_ns; + int64_t diff_ns; + +} test_log_t; + typedef struct test_global_t { struct { unsigned long long int period_ns; @@ -46,6 +54,7 @@ typedef struct test_global_t { unsigned long long int burst; int mode; int init; + int output; } opt;
test_stat_t stat; @@ -60,6 +69,9 @@ typedef struct test_global_t { uint64_t start_tick; uint64_t start_ns; uint64_t period_tick; + test_log_t *log; + FILE *file; + char filename[MAX_FILENAME + 1];
} test_global_t;
@@ -78,6 +90,7 @@ static void print_usage(void) " 0: Set all timers at init phase.\n" " 1: Set first burst of timers at init. Restart timers during test with absolute time.\n" " 2: Set first burst of timers at init. Restart timers during test with relative time.\n" + " -o, --output <file> Output file for measurement logs\n" " -i, --init Set global init parameters. Default: init params not set.\n" " -h, --help Display help and exit.\n\n"); } @@ -92,11 +105,12 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) {"num", required_argument, NULL, 'n'}, {"burst", required_argument, NULL, 'b'}, {"mode", required_argument, NULL, 'm'}, + {"output", required_argument, NULL, 'o'}, {"init", no_argument, NULL, 'i'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; - const char *shortopts = "+p:r:f:n:b:m:ih"; + const char *shortopts = "+p:r:f:n:b:m:o:ih"; int ret = 0;
test_global->opt.period_ns = 200 * ODP_TIME_MSEC_IN_NS; @@ -106,6 +120,7 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) test_global->opt.burst = 1; test_global->opt.mode = 0; test_global->opt.init = 0; + test_global->opt.output = 0;
while (1) { opt = getopt_long(argc, argv, shortopts, longopts, &long_index); @@ -132,6 +147,11 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) case 'm': test_global->opt.mode = atoi(optarg); break; + case 'o': + test_global->opt.output = 1; + /* filename is NULL terminated in anycase */ + strncpy(test_global->filename, optarg, MAX_FILENAME); + break; case 'i': test_global->opt.init = 1; break; @@ -265,6 +285,8 @@ static int start_timers(test_global_t *test_global) printf(" resolution capa: %" PRIu64 " nsec\n", res_capa); printf(" max timers capa: %" PRIu32 "\n", timer_capa.max_timers); printf(" mode: %i\n", mode); + if (test_global->opt.output) + printf(" log file: %s\n", test_global->filename); printf(" start offset: %" PRIu64 " nsec\n", offset_ns); printf(" period: %" PRIu64 " nsec\n", period_ns); printf(" resolution: %" PRIu64 " nsec\n", timer_param.res_ns); @@ -405,9 +427,11 @@ static int destroy_timers(test_global_t *test_global)
static void print_stat(test_global_t *test_global) { + uint64_t i; uint64_t tot_timers = test_global->tot_timers; uint64_t res_ns = test_global->opt.res_ns; test_stat_t *stat = &test_global->stat; + test_log_t *log = test_global->log; double ave_after = 0.0; double ave_before = 0.0;
@@ -421,6 +445,19 @@ static void print_stat(test_global_t *test_global) else stat->nsec_before_min = 0;
+ if (log) { + FILE *file = test_global->file; + + fprintf(file, " Timer tmo(ns) diff(ns)\n"); + + for (i = 0; i < tot_timers; i++) { + fprintf(file, "%8" PRIu64 " %12" PRIu64 " %10" + PRIi64 "\n", i, log[i].tmo_ns, log[i].diff_ns); + } + + fprintf(file, "\n"); + } + printf("\n Test results:\n"); printf(" num after: %12" PRIu64 " / %.2f%%\n", stat->num_after, 100.0 * stat->num_after / tot_timers); @@ -447,7 +484,8 @@ static void print_stat(test_global_t *test_global)
static void run_test(test_global_t *test_global) { - uint64_t num_left, burst, num, num_tmo, next_tmo; + uint64_t burst, num, num_tmo, next_tmo; + uint64_t i, tot_timers; odp_event_t ev; odp_time_t time; uint64_t time_ns, diff_ns, period_ns; @@ -455,16 +493,17 @@ static void run_test(test_global_t *test_global) uint64_t tmo_ns; timer_ctx_t *ctx; test_stat_t *stat = &test_global->stat; + test_log_t *log = test_global->log; int mode = test_global->opt.mode;
num = 0; next_tmo = 1; num_tmo = test_global->opt.num; burst = test_global->opt.burst; - num_left = test_global->tot_timers; + tot_timers = test_global->tot_timers; period_ns = test_global->period_ns;
- while (num_left) { + for (i = 0; i < tot_timers; i++) { ev = odp_schedule(NULL, ODP_SCHED_WAIT);
time = odp_time_local(); @@ -481,6 +520,10 @@ static void run_test(test_global_t *test_global) stat->nsec_after_min = diff_ns; if (diff_ns > stat->nsec_after_max) stat->nsec_after_max = diff_ns; + if (log) { + log[i].tmo_ns = tmo_ns; + log[i].diff_ns = diff_ns; + }
} else if (time_ns < tmo_ns) { diff_ns = tmo_ns - time_ns; @@ -490,7 +533,10 @@ static void run_test(test_global_t *test_global) stat->nsec_before_min = diff_ns; if (diff_ns > stat->nsec_before_max) stat->nsec_before_max = diff_ns; - + if (log) { + log[i].tmo_ns = tmo_ns; + log[i].diff_ns = -diff_ns; + } } else { stat->num_exact++; } @@ -531,7 +577,6 @@ static void run_test(test_global_t *test_global) odp_event_free(ev); }
- num_left--; num++;
if (num == burst) { @@ -564,6 +609,15 @@ int main(int argc, char *argv[]) if (parse_options(argc, argv, &test_global)) return -1;
+ if (test_global.opt.output) { + test_global.file = fopen(test_global.filename, "w"); + if (test_global.file == NULL) { + printf("Failed to open file: %s\n", + test_global.filename); + return -1; + } + } + /* List features not to be used (may optimize performance) */ odp_init_param_init(&init); init.not_used.feat.cls = 1; @@ -600,6 +654,16 @@ int main(int argc, char *argv[]) goto quit; }
+ if (test_global.opt.output) { + test_global.log = calloc(test_global.tot_timers, + sizeof(test_log_t)); + + if (test_global.log == NULL) { + printf("Test log calloc failed.\n"); + goto quit; + } + } + if (start_timers(&test_global)) goto quit;
@@ -608,12 +672,18 @@ int main(int argc, char *argv[]) print_stat(&test_global);
quit: + if (test_global.file) + fclose(test_global.file); + if (destroy_timers(&test_global)) ret = -1;
if (test_global.timer_ctx) free(test_global.timer_ctx);
+ if (test_global.log) + free(test_global.log); + if (odp_term_local()) { printf("Term local failed.\n"); ret = -1;
commit 1b103ac26cf40df3c091c344418881c6013669da Author: Petri Savolainen petri.savolainen@nokia.com Date: Fri Nov 22 11:08:21 2019 +0200
example: timer_accur: add mode option
Added --mode option to choose if all timers are set during test init, or reset after expiration. The latter allows running the test for a long time with a low number of timers allocated.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com
diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c index 24759b0e5..36827ad59 100644 --- a/example/timer/odp_timer_accuracy.c +++ b/example/timer/odp_timer_accuracy.c @@ -44,6 +44,7 @@ typedef struct test_global_t { unsigned long long int offset_ns; unsigned long long int num; unsigned long long int burst; + int mode; int init; } opt;
@@ -54,8 +55,11 @@ typedef struct test_global_t { odp_pool_t timeout_pool; timer_ctx_t *timer_ctx; uint64_t period_ns; - uint64_t first_ns; uint64_t tot_timers; + uint64_t alloc_timers; + uint64_t start_tick; + uint64_t start_ns; + uint64_t period_tick;
} test_global_t;
@@ -70,6 +74,10 @@ static void print_usage(void) " -f, --first <nsec> First timer offset in nsec. Default: 300 msec\n" " -n, --num <number> Number of timeouts. Default: 50\n" " -b, --burst <number> Number of timers per timeout. Default: 1\n" + " -m, --mode <number> Test mode select (default: 0):\n" + " 0: Set all timers at init phase.\n" + " 1: Set first burst of timers at init. Restart timers during test with absolute time.\n" + " 2: Set first burst of timers at init. Restart timers during test with relative time.\n" " -i, --init Set global init parameters. Default: init params not set.\n" " -h, --help Display help and exit.\n\n"); } @@ -83,11 +91,12 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) {"first", required_argument, NULL, 'f'}, {"num", required_argument, NULL, 'n'}, {"burst", required_argument, NULL, 'b'}, + {"mode", required_argument, NULL, 'm'}, {"init", no_argument, NULL, 'i'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; - const char *shortopts = "+p:r:f:n:b:ih"; + const char *shortopts = "+p:r:f:n:b:m:ih"; int ret = 0;
test_global->opt.period_ns = 200 * ODP_TIME_MSEC_IN_NS; @@ -95,6 +104,7 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) test_global->opt.offset_ns = 300 * ODP_TIME_MSEC_IN_NS; test_global->opt.num = 50; test_global->opt.burst = 1; + test_global->opt.mode = 0; test_global->opt.init = 0;
while (1) { @@ -119,6 +129,9 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) case 'b': test_global->opt.burst = strtoull(optarg, NULL, 0); break; + case 'm': + test_global->opt.mode = atoi(optarg); + break; case 'i': test_global->opt.init = 1; break; @@ -138,6 +151,11 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global)
test_global->tot_timers = test_global->opt.num * test_global->opt.burst;
+ if (test_global->opt.mode) + test_global->alloc_timers = test_global->opt.burst; + else + test_global->alloc_timers = test_global->tot_timers; + return ret; }
@@ -157,8 +175,11 @@ static int start_timers(test_global_t *test_global) odp_timeout_t timeout; odp_timer_set_t ret; odp_time_t time; - uint64_t i, j, idx, num_tmo, burst, tot_timers; + uint64_t i, j, idx, num_tmo, burst, tot_timers, alloc_timers; + int mode;
+ mode = test_global->opt.mode; + alloc_timers = test_global->alloc_timers; tot_timers = test_global->tot_timers; num_tmo = test_global->opt.num; burst = test_global->opt.burst; @@ -170,7 +191,7 @@ static int start_timers(test_global_t *test_global) test_global->timer_pool = ODP_TIMER_POOL_INVALID; test_global->timeout_pool = ODP_POOL_INVALID;
- for (i = 0; i < tot_timers; i++) { + for (i = 0; i < alloc_timers; i++) { test_global->timer_ctx[i].timer = ODP_TIMER_INVALID; test_global->timer_ctx[i].event = ODP_EVENT_INVALID; } @@ -191,7 +212,7 @@ static int start_timers(test_global_t *test_global)
odp_pool_param_init(&pool_param); pool_param.type = ODP_POOL_TIMEOUT; - pool_param.tmo.num = tot_timers; + pool_param.tmo.num = alloc_timers;
pool = odp_pool_create("timeout pool", &pool_param);
@@ -208,9 +229,9 @@ static int start_timers(test_global_t *test_global) }
if (timer_capa.max_timers && - test_global->tot_timers > timer_capa.max_timers) { + test_global->alloc_timers > timer_capa.max_timers) { printf("Error: Too many timers: %" PRIu64 ".\n" - " Max timers: %u\n", test_global->tot_timers, + " Max timers: %u\n", test_global->alloc_timers, timer_capa.max_timers); return -1; } @@ -231,14 +252,19 @@ static int start_timers(test_global_t *test_global) memset(&timer_param, 0, sizeof(odp_timer_pool_param_t));
timer_param.res_ns = res_ns; - timer_param.min_tmo = offset_ns / 2; + if (mode) + timer_param.min_tmo = period_ns / 10; + else + timer_param.min_tmo = offset_ns / 2; + timer_param.max_tmo = offset_ns + ((num_tmo + 1) * period_ns); - timer_param.num_timers = tot_timers; + timer_param.num_timers = alloc_timers; timer_param.clk_src = ODP_CLOCK_CPU;
printf("\nTest parameters:\n"); printf(" resolution capa: %" PRIu64 " nsec\n", res_capa); printf(" max timers capa: %" PRIu32 "\n", timer_capa.max_timers); + printf(" mode: %i\n", mode); printf(" start offset: %" PRIu64 " nsec\n", offset_ns); printf(" period: %" PRIu64 " nsec\n", period_ns); printf(" resolution: %" PRIu64 " nsec\n", timer_param.res_ns); @@ -247,6 +273,7 @@ static int start_timers(test_global_t *test_global) printf(" num timeout: %" PRIu64 "\n", num_tmo); printf(" burst size: %" PRIu64 "\n", burst); printf(" total timers: %" PRIu64 "\n", tot_timers); + printf(" alloc timers: %" PRIu64 "\n", alloc_timers); printf(" test run time: %.2f sec\n\n", (offset_ns + (num_tmo * period_ns)) / 1000000000.0);
@@ -264,7 +291,7 @@ static int start_timers(test_global_t *test_global)
test_global->timer_pool = timer_pool;
- for (i = 0; i < tot_timers; i++) { + for (i = 0; i < alloc_timers; i++) { timer_ctx_t *ctx = &test_global->timer_ctx[i];
timer = odp_timer_alloc(timer_pool, queue, ctx); @@ -300,7 +327,14 @@ static int start_timers(test_global_t *test_global) start_tick = odp_timer_current_tick(timer_pool); time = odp_time_local(); start_ns = odp_time_to_ns(time); - test_global->first_ns = start_ns + offset_ns; + + test_global->start_tick = start_tick; + test_global->start_ns = start_ns; + test_global->period_tick = odp_timer_ns_to_tick(timer_pool, period_ns); + + /* When mode is 1, set only one burst of timers initially */ + if (mode) + num_tmo = 1;
for (i = 0; i < num_tmo; i++) { nsec = offset_ns + (i * period_ns); @@ -330,14 +364,14 @@ static int start_timers(test_global_t *test_global)
static int destroy_timers(test_global_t *test_global) { - uint64_t i, tot_timers; + uint64_t i, alloc_timers; odp_timer_t timer; odp_event_t ev; int ret = 0;
- tot_timers = test_global->tot_timers; + alloc_timers = test_global->alloc_timers;
- for (i = 0; i < tot_timers; i++) { + for (i = 0; i < alloc_timers; i++) { timer = test_global->timer_ctx[i].timer;
if (timer == ODP_TIMER_INVALID) @@ -413,25 +447,34 @@ static void print_stat(test_global_t *test_global)
static void run_test(test_global_t *test_global) { - uint64_t num_left, burst, num; + uint64_t num_left, burst, num, num_tmo, next_tmo; odp_event_t ev; odp_time_t time; - uint64_t time_ns, diff_ns, next_tmo; + uint64_t time_ns, diff_ns, period_ns; + odp_timeout_t tmo; + uint64_t tmo_ns; + timer_ctx_t *ctx; test_stat_t *stat = &test_global->stat; + int mode = test_global->opt.mode;
num = 0; + next_tmo = 1; + num_tmo = test_global->opt.num; burst = test_global->opt.burst; num_left = test_global->tot_timers; - next_tmo = test_global->first_ns; + period_ns = test_global->period_ns;
while (num_left) { ev = odp_schedule(NULL, ODP_SCHED_WAIT);
time = odp_time_local(); time_ns = odp_time_to_ns(time); + tmo = odp_timeout_from_event(ev); + ctx = odp_timeout_user_ptr(tmo); + tmo_ns = ctx->nsec;
- if (time_ns > next_tmo) { - diff_ns = time_ns - next_tmo; + if (time_ns > tmo_ns) { + diff_ns = time_ns - tmo_ns; stat->num_after++; stat->nsec_after_sum += diff_ns; if (diff_ns < stat->nsec_after_min) @@ -439,8 +482,8 @@ static void run_test(test_global_t *test_global) if (diff_ns > stat->nsec_after_max) stat->nsec_after_max = diff_ns;
- } else if (time_ns < next_tmo) { - diff_ns = next_tmo - time_ns; + } else if (time_ns < tmo_ns) { + diff_ns = tmo_ns - time_ns; stat->num_before++; stat->nsec_before_sum += diff_ns; if (diff_ns < stat->nsec_before_min) @@ -452,15 +495,50 @@ static void run_test(test_global_t *test_global) stat->num_exact++; }
- odp_event_free(ev); + if (mode && next_tmo < num_tmo) { + /* Reset timer for next period */ + odp_timer_t timer; + uint64_t nsec, tick; + odp_timer_set_t ret; + odp_timer_pool_t timer_pool = test_global->timer_pool; + + timer = ctx->timer; + + if (mode == 1) { + /* Absolute time */ + ctx->nsec += period_ns; + nsec = ctx->nsec - test_global->start_ns; + tick = test_global->start_tick + + odp_timer_ns_to_tick(timer_pool, nsec); + + ret = odp_timer_set_abs(timer, tick, &ev); + } else { + /* Relative time */ + tick = test_global->period_tick; + time = odp_time_local(); + time_ns = odp_time_to_ns(time); + ctx->nsec = time_ns + period_ns; + + ret = odp_timer_set_rel(timer, tick, &ev); + } + + if (ret != ODP_TIMER_SUCCESS) { + printf("Timer set failed: %i. Timeout nsec " + "%" PRIu64 "\n", ret, ctx->nsec); + return; + } + } else { + odp_event_free(ev); + }
num_left--; num++;
if (num == burst) { - next_tmo += test_global->period_ns; + next_tmo++; num = 0; } + }
/* Free current scheduler context. There should be no more events. */ @@ -514,7 +592,7 @@ int main(int argc, char *argv[]) /* Configure scheduler */ odp_schedule_config(NULL);
- test_global.timer_ctx = calloc(test_global.tot_timers, + test_global.timer_ctx = calloc(test_global.alloc_timers, sizeof(timer_ctx_t));
if (test_global.timer_ctx == NULL) {
commit a6241a89c18dd7a4a14214a100369f5ef46f25ef Author: Petri Savolainen petri.savolainen@nokia.com Date: Fri Nov 22 11:07:20 2019 +0200
example: timer_accur: add timer burst option
Added command line option (--burst) to set multiple timers for each timeout period. Total number of timers is number of timeout periods (--num) times the burst size.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com
diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c index 4c33329cb..24759b0e5 100644 --- a/example/timer/odp_timer_accuracy.c +++ b/example/timer/odp_timer_accuracy.c @@ -15,6 +15,13 @@
#include <odp_api.h>
+typedef struct timer_ctx_t { + odp_timer_t timer; + odp_event_t event; + uint64_t nsec; + +} timer_ctx_t; + typedef struct { uint64_t nsec_before_sum; uint64_t nsec_before_min; @@ -35,7 +42,8 @@ typedef struct test_global_t { unsigned long long int period_ns; unsigned long long int res_ns; unsigned long long int offset_ns; - int num; + unsigned long long int num; + unsigned long long int burst; int init; } opt;
@@ -44,9 +52,10 @@ typedef struct test_global_t { odp_queue_t queue; odp_timer_pool_t timer_pool; odp_pool_t timeout_pool; - odp_timer_t *timer; + timer_ctx_t *timer_ctx; uint64_t period_ns; uint64_t first_ns; + uint64_t tot_timers;
} test_global_t;
@@ -60,6 +69,7 @@ static void print_usage(void) " -r, --resolution <nsec> Timeout resolution in nsec. Default: period / 10\n" " -f, --first <nsec> First timer offset in nsec. Default: 300 msec\n" " -n, --num <number> Number of timeouts. Default: 50\n" + " -b, --burst <number> Number of timers per timeout. Default: 1\n" " -i, --init Set global init parameters. Default: init params not set.\n" " -h, --help Display help and exit.\n\n"); } @@ -72,17 +82,19 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) {"resolution", required_argument, NULL, 'r'}, {"first", required_argument, NULL, 'f'}, {"num", required_argument, NULL, 'n'}, + {"burst", required_argument, NULL, 'b'}, {"init", no_argument, NULL, 'i'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; - const char *shortopts = "+p:r:f:n:ih"; + const char *shortopts = "+p:r:f:n:b:ih"; int ret = 0;
test_global->opt.period_ns = 200 * ODP_TIME_MSEC_IN_NS; test_global->opt.res_ns = 0; test_global->opt.offset_ns = 300 * ODP_TIME_MSEC_IN_NS; test_global->opt.num = 50; + test_global->opt.burst = 1; test_global->opt.init = 0;
while (1) { @@ -102,7 +114,10 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) test_global->opt.offset_ns = strtoull(optarg, NULL, 0); break; case 'n': - test_global->opt.num = atoi(optarg); + test_global->opt.num = strtoull(optarg, NULL, 0); + break; + case 'b': + test_global->opt.burst = strtoull(optarg, NULL, 0); break; case 'i': test_global->opt.init = 1; @@ -121,6 +136,8 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) if (test_global->opt.res_ns == 0) test_global->opt.res_ns = test_global->opt.period_ns / 10;
+ test_global->tot_timers = test_global->opt.num * test_global->opt.burst; + return ret; }
@@ -140,9 +157,11 @@ static int start_timers(test_global_t *test_global) odp_timeout_t timeout; odp_timer_set_t ret; odp_time_t time; - int i, num; + uint64_t i, j, idx, num_tmo, burst, tot_timers;
- num = test_global->opt.num; + tot_timers = test_global->tot_timers; + num_tmo = test_global->opt.num; + burst = test_global->opt.burst; period_ns = test_global->opt.period_ns; test_global->period_ns = period_ns;
@@ -151,8 +170,10 @@ static int start_timers(test_global_t *test_global) test_global->timer_pool = ODP_TIMER_POOL_INVALID; test_global->timeout_pool = ODP_POOL_INVALID;
- for (i = 0; i < num; i++) - test_global->timer[i] = ODP_TIMER_INVALID; + for (i = 0; i < tot_timers; i++) { + test_global->timer_ctx[i].timer = ODP_TIMER_INVALID; + test_global->timer_ctx[i].event = ODP_EVENT_INVALID; + }
odp_queue_param_init(&queue_param); queue_param.type = ODP_QUEUE_TYPE_SCHED; @@ -170,7 +191,7 @@ static int start_timers(test_global_t *test_global)
odp_pool_param_init(&pool_param); pool_param.type = ODP_POOL_TIMEOUT; - pool_param.tmo.num = num; + pool_param.tmo.num = tot_timers;
pool = odp_pool_create("timeout pool", &pool_param);
@@ -186,6 +207,14 @@ static int start_timers(test_global_t *test_global) return -1; }
+ if (timer_capa.max_timers && + test_global->tot_timers > timer_capa.max_timers) { + printf("Error: Too many timers: %" PRIu64 ".\n" + " Max timers: %u\n", test_global->tot_timers, + timer_capa.max_timers); + return -1; + } + res_capa = timer_capa.highest_res_ns;
offset_ns = test_global->opt.offset_ns; @@ -203,20 +232,23 @@ static int start_timers(test_global_t *test_global)
timer_param.res_ns = res_ns; timer_param.min_tmo = offset_ns / 2; - timer_param.max_tmo = offset_ns + ((num + 1) * period_ns); - timer_param.num_timers = num; + timer_param.max_tmo = offset_ns + ((num_tmo + 1) * period_ns); + timer_param.num_timers = tot_timers; timer_param.clk_src = ODP_CLOCK_CPU;
printf("\nTest parameters:\n"); printf(" resolution capa: %" PRIu64 " nsec\n", res_capa); + printf(" max timers capa: %" PRIu32 "\n", timer_capa.max_timers); printf(" start offset: %" PRIu64 " nsec\n", offset_ns); printf(" period: %" PRIu64 " nsec\n", period_ns); printf(" resolution: %" PRIu64 " nsec\n", timer_param.res_ns); printf(" min timeout: %" PRIu64 " nsec\n", timer_param.min_tmo); printf(" max timeout: %" PRIu64 " nsec\n", timer_param.max_tmo); - printf(" num timers: %u\n", timer_param.num_timers); - printf(" test run time: %.1f sec\n\n", - timer_param.max_tmo / 1000000000.0); + printf(" num timeout: %" PRIu64 "\n", num_tmo); + printf(" burst size: %" PRIu64 "\n", burst); + printf(" total timers: %" PRIu64 "\n", tot_timers); + printf(" test run time: %.2f sec\n\n", + (offset_ns + (num_tmo * period_ns)) / 1000000000.0);
timer_pool = odp_timer_pool_create("timer_accuracy", &timer_param);
@@ -232,15 +264,25 @@ static int start_timers(test_global_t *test_global)
test_global->timer_pool = timer_pool;
- for (i = 0; i < num; i++) { - timer = odp_timer_alloc(timer_pool, queue, NULL); + for (i = 0; i < tot_timers; i++) { + timer_ctx_t *ctx = &test_global->timer_ctx[i]; + + timer = odp_timer_alloc(timer_pool, queue, ctx);
if (timer == ODP_TIMER_INVALID) { printf("Timer alloc failed.\n"); return -1; }
- test_global->timer[i] = timer; + ctx->timer = timer; + + timeout = odp_timeout_alloc(pool); + if (timeout == ODP_TIMEOUT_INVALID) { + printf("Timeout alloc failed\n"); + return -1; + } + + ctx->event = odp_timeout_to_event(timeout); }
/* Run scheduler few times to ensure that (software) timer is active */ @@ -254,30 +296,32 @@ static int start_timers(test_global_t *test_global) } }
+ idx = 0; start_tick = odp_timer_current_tick(timer_pool); time = odp_time_local(); start_ns = odp_time_to_ns(time); test_global->first_ns = start_ns + offset_ns;
- for (i = 0; i < num; i++) { - timer = test_global->timer[i]; + for (i = 0; i < num_tmo; i++) { + nsec = offset_ns + (i * period_ns); + tick = start_tick + odp_timer_ns_to_tick(timer_pool, nsec);
- timeout = odp_timeout_alloc(pool); - if (timeout == ODP_TIMEOUT_INVALID) { - printf("Timeout alloc failed\n"); - return -1; - } + for (j = 0; j < burst; j++) { + timer_ctx_t *ctx = &test_global->timer_ctx[idx];
- event = odp_timeout_to_event(timeout); + timer = ctx->timer; + event = ctx->event; + ctx->nsec = start_ns + nsec;
- nsec = offset_ns + (i * period_ns); - tick = start_tick + odp_timer_ns_to_tick(timer_pool, nsec); + ret = odp_timer_set_abs(timer, tick, &event);
- ret = odp_timer_set_abs(timer, tick, &event); + if (ret != ODP_TIMER_SUCCESS) { + printf("Timer[%" PRIu64 "] set failed: %i\n", + idx, ret); + return -1; + }
- if (ret != ODP_TIMER_SUCCESS) { - printf("Timer[%i] set failed: ret %i\n", i, ret); - return -1; + idx++; } }
@@ -286,15 +330,15 @@ static int start_timers(test_global_t *test_global)
static int destroy_timers(test_global_t *test_global) { - int i, num; + uint64_t i, tot_timers; odp_timer_t timer; odp_event_t ev; int ret = 0;
- num = test_global->opt.num; + tot_timers = test_global->tot_timers;
- for (i = 0; i < num; i++) { - timer = test_global->timer[i]; + for (i = 0; i < tot_timers; i++) { + timer = test_global->timer_ctx[i].timer;
if (timer == ODP_TIMER_INVALID) break; @@ -327,7 +371,7 @@ static int destroy_timers(test_global_t *test_global)
static void print_stat(test_global_t *test_global) { - uint64_t num = test_global->opt.num; + uint64_t tot_timers = test_global->tot_timers; uint64_t res_ns = test_global->opt.res_ns; test_stat_t *stat = &test_global->stat; double ave_after = 0.0; @@ -345,11 +389,11 @@ static void print_stat(test_global_t *test_global)
printf("\n Test results:\n"); printf(" num after: %12" PRIu64 " / %.2f%%\n", - stat->num_after, 100.0 * stat->num_after / num); + stat->num_after, 100.0 * stat->num_after / tot_timers); printf(" num before: %12" PRIu64 " / %.2f%%\n", - stat->num_before, 100.0 * stat->num_before / num); + stat->num_before, 100.0 * stat->num_before / tot_timers); printf(" num exact: %12" PRIu64 " / %.2f%%\n", - stat->num_exact, 100.0 * stat->num_exact / num); + stat->num_exact, 100.0 * stat->num_exact / tot_timers); printf(" error after (nsec):\n"); printf(" min: %12" PRIu64 " / %.3fx resolution\n", stat->nsec_after_min, (double)stat->nsec_after_min / res_ns); @@ -369,14 +413,15 @@ static void print_stat(test_global_t *test_global)
static void run_test(test_global_t *test_global) { - int num, num_left; + uint64_t num_left, burst, num; odp_event_t ev; odp_time_t time; uint64_t time_ns, diff_ns, next_tmo; test_stat_t *stat = &test_global->stat;
- num = test_global->opt.num; - num_left = num; + num = 0; + burst = test_global->opt.burst; + num_left = test_global->tot_timers; next_tmo = test_global->first_ns;
while (num_left) { @@ -409,8 +454,13 @@ static void run_test(test_global_t *test_global)
odp_event_free(ev);
- next_tmo += test_global->period_ns; num_left--; + num++; + + if (num == burst) { + next_tmo += test_global->period_ns; + num = 0; + } }
/* Free current scheduler context. There should be no more events. */ @@ -425,7 +475,6 @@ int main(int argc, char *argv[]) { odp_instance_t instance; odp_init_t init; - int num; test_global_t test_global; odp_init_t *init_ptr = NULL; int ret = 0; @@ -465,12 +514,11 @@ int main(int argc, char *argv[]) /* Configure scheduler */ odp_schedule_config(NULL);
- num = test_global.opt.num; - - test_global.timer = calloc(num, sizeof(odp_timer_t)); + test_global.timer_ctx = calloc(test_global.tot_timers, + sizeof(timer_ctx_t));
- if (test_global.timer == NULL) { - printf("Malloc failed.\n"); + if (test_global.timer_ctx == NULL) { + printf("Timer context table calloc failed.\n"); goto quit; }
@@ -485,8 +533,8 @@ quit: if (destroy_timers(&test_global)) ret = -1;
- if (test_global.timer) - free(test_global.timer); + if (test_global.timer_ctx) + free(test_global.timer_ctx);
if (odp_term_local()) { printf("Term local failed.\n");
commit 11bd13b261d291fd5b169e4a02c21d217fbf70ac Author: Petri Savolainen petri.savolainen@nokia.com Date: Thu Nov 21 13:04:33 2019 +0200
example: timer_accur: statistics print function
Move statistics print into a function, so that it can be reused by a new test case.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com
diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c index 35c8c612d..4c33329cb 100644 --- a/example/timer/odp_timer_accuracy.c +++ b/example/timer/odp_timer_accuracy.c @@ -1,4 +1,5 @@ /* Copyright (c) 2018, Linaro Limited + * Copyright (c) 2019, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -14,6 +15,21 @@
#include <odp_api.h>
+typedef struct { + uint64_t nsec_before_sum; + uint64_t nsec_before_min; + uint64_t nsec_before_max; + + uint64_t nsec_after_sum; + uint64_t nsec_after_min; + uint64_t nsec_after_max; + + uint64_t num_before; + uint64_t num_exact; + uint64_t num_after; + +} test_stat_t; + typedef struct test_global_t { struct { unsigned long long int period_ns; @@ -23,6 +39,8 @@ typedef struct test_global_t { int init; } opt;
+ test_stat_t stat; + odp_queue_t queue; odp_timer_pool_t timer_pool; odp_pool_t timeout_pool; @@ -307,25 +325,56 @@ static int destroy_timers(test_global_t *test_global) return ret; }
+static void print_stat(test_global_t *test_global) +{ + uint64_t num = test_global->opt.num; + uint64_t res_ns = test_global->opt.res_ns; + test_stat_t *stat = &test_global->stat; + double ave_after = 0.0; + double ave_before = 0.0; + + if (stat->num_after) + ave_after = (double)stat->nsec_after_sum / stat->num_after; + else + stat->nsec_after_min = 0; + + if (stat->num_before) + ave_before = (double)stat->nsec_before_sum / stat->num_before; + else + stat->nsec_before_min = 0; + + printf("\n Test results:\n"); + printf(" num after: %12" PRIu64 " / %.2f%%\n", + stat->num_after, 100.0 * stat->num_after / num); + printf(" num before: %12" PRIu64 " / %.2f%%\n", + stat->num_before, 100.0 * stat->num_before / num); + printf(" num exact: %12" PRIu64 " / %.2f%%\n", + stat->num_exact, 100.0 * stat->num_exact / num); + printf(" error after (nsec):\n"); + printf(" min: %12" PRIu64 " / %.3fx resolution\n", + stat->nsec_after_min, (double)stat->nsec_after_min / res_ns); + printf(" max: %12" PRIu64 " / %.3fx resolution\n", + stat->nsec_after_max, (double)stat->nsec_after_max / res_ns); + printf(" ave: %12.0f / %.3fx resolution\n", + ave_after, ave_after / res_ns); + printf(" error before (nsec):\n"); + printf(" min: %12" PRIu64 " / %.3fx resolution\n", + stat->nsec_before_min, (double)stat->nsec_before_min / res_ns); + printf(" max: %12" PRIu64 " / %.3fx resolution\n", + stat->nsec_before_max, (double)stat->nsec_before_max / res_ns); + printf(" ave: %12.0f / %.3fx resolution\n", + ave_before, ave_before / res_ns); + printf("\n"); +} + static void run_test(test_global_t *test_global) { int num, num_left; odp_event_t ev; odp_time_t time; - uint64_t time_ns, diff_ns, next_tmo, res_ns; - uint64_t after = 0; - uint64_t min_after = UINT64_MAX; - uint64_t max_after = 0; - uint64_t before = 0; - uint64_t min_before = UINT64_MAX; - uint64_t max_before = 0; - double ave_after = 0.0; - double ave_before = 0.0; - int num_after = 0; - int num_exact = 0; - int num_before = 0; + uint64_t time_ns, diff_ns, next_tmo; + test_stat_t *stat = &test_global->stat;
- res_ns = test_global->opt.res_ns; num = test_global->opt.num; num_left = num; next_tmo = test_global->first_ns; @@ -338,24 +387,24 @@ static void run_test(test_global_t *test_global)
if (time_ns > next_tmo) { diff_ns = time_ns - next_tmo; - num_after++; - after += diff_ns; - if (diff_ns < min_after) - min_after = diff_ns; - if (diff_ns > max_after) - max_after = diff_ns; + stat->num_after++; + stat->nsec_after_sum += diff_ns; + if (diff_ns < stat->nsec_after_min) + stat->nsec_after_min = diff_ns; + if (diff_ns > stat->nsec_after_max) + stat->nsec_after_max = diff_ns;
} else if (time_ns < next_tmo) { diff_ns = next_tmo - time_ns; - num_before++; - before += diff_ns; - if (diff_ns < min_before) - min_before = diff_ns; - if (diff_ns > max_before) - max_before = diff_ns; + stat->num_before++; + stat->nsec_before_sum += diff_ns; + if (diff_ns < stat->nsec_before_min) + stat->nsec_before_min = diff_ns; + if (diff_ns > stat->nsec_before_max) + stat->nsec_before_max = diff_ns;
} else { - num_exact++; + stat->num_exact++; }
odp_event_free(ev); @@ -370,39 +419,6 @@ static void run_test(test_global_t *test_global) printf("Dropping extra event\n"); odp_event_free(ev); } - - if (num_after) - ave_after = (double)after / num_after; - else - min_after = 0; - - if (num_before) - ave_before = (double)before / num_before; - else - min_before = 0; - - printf("\n Test results:\n"); - printf(" num after: %12i / %.2f%%\n", - num_after, 100.0 * num_after / num); - printf(" num before: %12i / %.2f%%\n", - num_before, 100.0 * num_before / num); - printf(" num exact: %12i / %.2f%%\n", - num_exact, 100.0 * num_exact / num); - printf(" error after (nsec):\n"); - printf(" min: %12" PRIu64 " / %.3fx resolution\n", - min_after, (double)min_after / res_ns); - printf(" max: %12" PRIu64 " / %.3fx resolution\n", - max_after, (double)max_after / res_ns); - printf(" ave: %12.0f / %.3fx resolution\n", - ave_after, ave_after / res_ns); - printf(" error before (nsec):\n"); - printf(" min: %12" PRIu64 " / %.3fx resolution\n", - min_before, (double)min_before / res_ns); - printf(" max: %12" PRIu64 " / %.3fx resolution\n", - max_before, (double)max_before / res_ns); - printf(" ave: %12.0f / %.3fx resolution\n", - ave_before, ave_before / res_ns); - printf("\n"); }
int main(int argc, char *argv[]) @@ -415,6 +431,8 @@ int main(int argc, char *argv[]) int ret = 0;
memset(&test_global, 0, sizeof(test_global_t)); + test_global.stat.nsec_before_min = UINT64_MAX; + test_global.stat.nsec_after_min = UINT64_MAX;
if (parse_options(argc, argv, &test_global)) return -1; @@ -461,6 +479,8 @@ int main(int argc, char *argv[])
run_test(&test_global);
+ print_stat(&test_global); + quit: if (destroy_timers(&test_global)) ret = -1;
-----------------------------------------------------------------------
Summary of changes: example/timer/odp_timer_accuracy.c | 489 +++++++++++++++++++++++++++---------- 1 file changed, 365 insertions(+), 124 deletions(-)
hooks/post-receive