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 79781031e28dee010425f575d1bf5de5b18af0d6 (commit) via 7d91fbd6c1a40e378b06f9be6dd3ef260c66dba9 (commit) from d189d704a29f490583057ccb5c762432a4e4b7a7 (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 79781031e28dee010425f575d1bf5de5b18af0d6 Author: Petri Savolainen petri.savolainen@linaro.org Date: Wed May 2 11:58:33 2018 +0300
example: timer_accuracy: simple timer accuracy measurement app
Added simple application to measure timer accuracy. Uses time API to measure accuracy of received timeouts from timer.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/example/timer/.gitignore b/example/timer/.gitignore index eaa9a361..2b077829 100644 --- a/example/timer/.gitignore +++ b/example/timer/.gitignore @@ -1,4 +1,5 @@ *.log *.trs +odp_timer_accuracy odp_timer_test odp_timer_simple diff --git a/example/timer/Makefile.am b/example/timer/Makefile.am index 64e722a3..c7d58922 100644 --- a/example/timer/Makefile.am +++ b/example/timer/Makefile.am @@ -1,11 +1,16 @@ include $(top_srcdir)/example/Makefile.inc
-bin_PROGRAMS = odp_timer_test \ - odp_timer_simple -odp_timer_test_SOURCES = odp_timer_test.c +bin_PROGRAMS = odp_timer_accuracy \ + odp_timer_simple \ + odp_timer_test + +odp_timer_accuracy_SOURCES = odp_timer_accuracy.c
odp_timer_simple_SOURCES = odp_timer_simple.c
+odp_timer_test_SOURCES = odp_timer_test.c + if test_example -TESTS = odp_timer_simple +TESTS = odp_timer_accuracy \ + odp_timer_simple endif diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c new file mode 100644 index 00000000..f1a088cb --- /dev/null +++ b/example/timer/odp_timer_accuracy.c @@ -0,0 +1,461 @@ +/* Copyright (c) 2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <stdlib.h> + +#include <unistd.h> +#include <getopt.h> + +#include <odp_api.h> + +#define START_OFFSET_NS ((uint64_t)(300 * ODP_TIME_MSEC_IN_NS)) + +typedef struct test_global_t { + struct { + unsigned long long int period_ns; + unsigned long long int res_ns; + int num; + int init; + } opt; + + odp_queue_t queue; + odp_timer_pool_t timer_pool; + odp_pool_t timeout_pool; + odp_timer_t *timer; + uint64_t period_ns; + uint64_t first_ns; + +} test_global_t; + +static void print_usage(void) +{ + printf("\n" + "Timer accuracy test application.\n" + "\n" + "OPTIONS:\n" + " -p, --period <nsec> Timeout period. Default: 200 milliseconds\n" + " -r, --resolution <nsec> Timeout resolution. Default: period / 10\n" + " -n, --num <number> Number of timeouts. Default: 50\n" + " -i, --init Set global init parameters. Default: init params not set.\n" + " -h, --help Display help and exit.\n\n"); +} + +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'}, + {"num", required_argument, NULL, 'n'}, + {"init", no_argument, NULL, 'i'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + const char *shortopts = "+p:r:n:ih"; + int ret = 0; + + test_global->opt.period_ns = 200 * ODP_TIME_MSEC_IN_NS; + test_global->opt.res_ns = 0; + test_global->opt.num = 50; + test_global->opt.init = 0; + + while (1) { + opt = getopt_long(argc, argv, shortopts, longopts, &long_index); + + if (opt == -1) + break; /* No more options */ + + switch (opt) { + case 'p': + test_global->opt.period_ns = strtoull(optarg, NULL, 0); + break; + case 'r': + test_global->opt.res_ns = strtoull(optarg, NULL, 0); + break; + case 'n': + test_global->opt.num = atoi(optarg); + break; + case 'i': + test_global->opt.init = 1; + break; + case 'h': + print_usage(); + ret = -1; + break; + default: + print_usage(); + ret = -1; + break; + } + } + + if (test_global->opt.res_ns == 0) + test_global->opt.res_ns = test_global->opt.period_ns / 10; + + return ret; +} + +static int start_timers(test_global_t *test_global) +{ + odp_pool_t pool; + odp_pool_param_t pool_param; + odp_timer_pool_t timer_pool; + odp_timer_pool_param_t timer_param; + odp_timer_capability_t timer_capa; + odp_timer_t timer; + odp_queue_t queue; + odp_queue_param_t queue_param; + uint64_t tick, first_tick, period_tick, offset_tick; + uint64_t period_ns, res_ns, first_ns, res_capa; + odp_event_t event; + odp_timeout_t timeout; + odp_timer_set_t ret; + odp_time_t time; + int i, num; + + num = test_global->opt.num; + period_ns = test_global->opt.period_ns; + test_global->period_ns = period_ns; + + /* Always init globals for destroy calls */ + test_global->queue = ODP_QUEUE_INVALID; + 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; + + odp_queue_param_init(&queue_param); + queue_param.type = ODP_QUEUE_TYPE_SCHED; + queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT; + queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; + queue_param.sched.group = ODP_SCHED_GROUP_ALL; + + queue = odp_queue_create("timeout_queue", &queue_param); + if (queue == ODP_QUEUE_INVALID) { + printf("Queue create failed.\n"); + return -1; + } + + test_global->queue = queue; + + odp_pool_param_init(&pool_param); + pool_param.type = ODP_POOL_TIMEOUT; + pool_param.tmo.num = num; + + pool = odp_pool_create("timeout pool", &pool_param); + + if (pool == ODP_POOL_INVALID) { + printf("Timeout pool create failed.\n"); + return -1; + } + + test_global->timeout_pool = pool; + + if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) { + printf("Timer capa failed\n"); + return -1; + } + + res_capa = timer_capa.highest_res_ns; + + res_ns = test_global->opt.res_ns; + + if (res_ns < res_capa) { + printf("Resolution %" PRIu64 " nsec too high. " + "Highest resolution %" PRIu64 " nsec. " + "Default resolution is period / 10.\n\n", + res_ns, res_capa); + return -1; + } + + memset(&timer_param, 0, sizeof(odp_timer_pool_param_t)); + + timer_param.res_ns = res_ns; + timer_param.min_tmo = period_ns; + timer_param.max_tmo = START_OFFSET_NS + (num * period_ns); + timer_param.num_timers = num; + timer_param.clk_src = ODP_CLOCK_CPU; + + printf("\nTest parameters:\n"); + printf(" resolution capa: %" PRIu64 " nsec\n", res_capa); + printf(" start offset: %" PRIu64 " nsec\n", START_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); + + timer_pool = odp_timer_pool_create("timer_accuracy", &timer_param); + + if (timer_pool == ODP_TIMER_POOL_INVALID) { + printf("Timer pool create failed\n"); + return -1; + } + + odp_timer_pool_start(); + + test_global->timer_pool = timer_pool; + first_tick = 0; + offset_tick = odp_timer_ns_to_tick(timer_pool, START_OFFSET_NS); + period_tick = odp_timer_ns_to_tick(timer_pool, period_ns); + + for (i = 0; i < num; i++) { + timer = odp_timer_alloc(timer_pool, queue, NULL); + + if (timer == ODP_TIMER_INVALID) { + printf("Timer alloc failed.\n"); + return -1; + } + + test_global->timer[i] = timer; + } + + for (i = 0; i < num; i++) { + timer = test_global->timer[i]; + + timeout = odp_timeout_alloc(pool); + if (timeout == ODP_TIMEOUT_INVALID) { + printf("Timeout alloc failed\n"); + return -1; + } + + event = odp_timeout_to_event(timeout); + + if (i == 0) { + first_tick = odp_timer_current_tick(timer_pool); + time = odp_time_local(); + first_ns = odp_time_to_ns(time); + test_global->first_ns = first_ns + START_OFFSET_NS; + } + + tick = first_tick + offset_tick + (i * period_tick); + ret = odp_timer_set_abs(timer, tick, &event); + + if (ret != ODP_TIMER_SUCCESS) { + printf("Timer[%i] set failed: ret %i\n", i, ret); + return -1; + } + } + + return 0; +} + +static int destroy_timers(test_global_t *test_global) +{ + int i, num; + odp_timer_t timer; + odp_event_t ev; + int ret = 0; + + num = test_global->opt.num; + + for (i = 0; i < num; i++) { + timer = test_global->timer[i]; + + if (timer == ODP_TIMER_INVALID) + break; + + ev = odp_timer_free(timer); + + if (ev != ODP_EVENT_INVALID) + odp_event_free(ev); + } + + if (test_global->timer_pool != ODP_TIMER_POOL_INVALID) + odp_timer_pool_destroy(test_global->timer_pool); + + if (test_global->timeout_pool != ODP_POOL_INVALID) { + if (odp_pool_destroy(test_global->timeout_pool)) { + printf("Pool destroy failed.\n"); + ret = -1; + } + } + + if (test_global->queue != ODP_QUEUE_INVALID) { + if (odp_queue_destroy(test_global->queue)) { + printf("Queue destroy failed.\n"); + ret = -1; + } + } + + return ret; +} + +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; + + res_ns = test_global->opt.res_ns; + num = test_global->opt.num; + num_left = num; + next_tmo = test_global->first_ns; + + while (num_left) { + ev = odp_schedule(NULL, ODP_SCHED_WAIT); + + time = odp_time_local(); + time_ns = odp_time_to_ns(time); + + 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; + + } 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; + + } else { + num_exact++; + } + + odp_event_free(ev); + + next_tmo += test_global->period_ns; + num_left--; + } + + /* Free current scheduler context. There should be no more events. */ + while ((ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT)) + != ODP_EVENT_INVALID) { + 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[]) +{ + odp_instance_t instance; + odp_init_t init; + int num; + test_global_t test_global; + odp_init_t *init_ptr = NULL; + int ret = 0; + + memset(&test_global, 0, sizeof(test_global_t)); + + if (parse_options(argc, argv, &test_global)) + return -1; + + /* List features not to be used (may optimize performance) */ + odp_init_param_init(&init); + init.not_used.feat.cls = 1; + init.not_used.feat.crypto = 1; + init.not_used.feat.ipsec = 1; + init.not_used.feat.tm = 1; + + if (test_global.opt.init) + init_ptr = &init; + + /* Init ODP before calling anything else */ + if (odp_init_global(&instance, init_ptr, NULL)) { + printf("Global init failed.\n"); + return -1; + } + + /* Init this thread */ + if (odp_init_local(instance, ODP_THREAD_WORKER)) { + printf("Local init failed.\n"); + return -1; + } + + odp_sys_info_print(); + + num = test_global.opt.num; + + test_global.timer = calloc(num, sizeof(odp_timer_t)); + + if (test_global.timer == NULL) { + printf("Malloc failed.\n"); + goto quit; + } + + if (start_timers(&test_global)) + goto quit; + + run_test(&test_global); + +quit: + if (destroy_timers(&test_global)) + ret = -1; + + if (test_global.timer) + free(test_global.timer); + + if (odp_term_local()) { + printf("Term local failed.\n"); + ret = -1; + } + + if (odp_term_global(instance)) { + printf("Term global failed.\n"); + ret = -1; + } + + return ret; +}
commit 7d91fbd6c1a40e378b06f9be6dd3ef260c66dba9 Author: Matias Elo matias.elo@nokia.com Date: Fri May 4 10:39:48 2018 +0300
linux-gen: packet: rearrange odp_packet_hdr_t members
Save 64 bytes by rearranging odp_packet_hdr_t members.
Signed-off-by: Matias Elo matias.elo@nokia.com Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index be17cac8..04112662 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -96,6 +96,9 @@ typedef struct { * Members below are not initialized by packet_init() */
+ /* Type of extra data */ + uint8_t extra_type; + /* Flow hash value */ uint32_t flow_hash;
@@ -108,16 +111,14 @@ typedef struct { /* Result for crypto packet op */ odp_crypto_packet_result_t crypto_op_result;
-#ifdef ODP_PKTIO_DPDK - /* Type of extra data */ - uint8_t extra_type; - /* Extra space for packet descriptors. E.g. DPDK mbuf */ - uint8_t ODP_ALIGNED_CACHE extra[PKT_EXTRA_LEN]; -#endif - /* Context for IPsec */ odp_ipsec_packet_result_t ipsec_ctx;
+#ifdef ODP_PKTIO_DPDK + /* Extra space for packet descriptors. E.g. DPDK mbuf. Keep as the last + * member before data. */ + uint8_t ODP_ALIGNED_CACHE extra[PKT_EXTRA_LEN]; +#endif /* Packet data storage */ uint8_t data[0]; } odp_packet_hdr_t;
-----------------------------------------------------------------------
Summary of changes: example/timer/.gitignore | 1 + example/timer/Makefile.am | 13 +- example/timer/odp_timer_accuracy.c | 461 +++++++++++++++++++++ .../linux-generic/include/odp_packet_internal.h | 15 +- 4 files changed, 479 insertions(+), 11 deletions(-) create mode 100644 example/timer/odp_timer_accuracy.c
hooks/post-receive