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 e2786e3ed30405b16da8080e2b0ed11b0fd52fc7 (commit) via 6c34ea307f8d9ab91d4e3d752468996fbf3a9fc4 (commit) via ccd90637cf66ef20219719cf636be2e84a93b9ad (commit) via 22dcfae29a2dc7f0ee00c6d807db1f4424bf9c63 (commit) via 4f0e6037a7037c0879062f2b1ead0503f45ae623 (commit) via 47fae268aef777b8d523dca43d0b50f8139bc8cf (commit) via 2600af0ade3c254ba00a935a38647d6d15611586 (commit) via 6280e54ea0a69276f3e1cbadd981f28dd2fb253a (commit) via b78412a08ad0435ace4d2980a38fa44b1fddbf96 (commit) via 5422332ff596b8cef9d5518b7bff6ab9b4b38b09 (commit) via 9eeb94e6d03923a67779314c62e32e410e1272d8 (commit) via 064dbc1d3b0d284ae7ab4db5e20fa0f6f2ce8c56 (commit) from 78364dc1d53a1a4c4918ce0a82d02fe56f0abb54 (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 e2786e3ed30405b16da8080e2b0ed11b0fd52fc7 Author: Petri Savolainen petri.savolainen@nokia.com Date: Mon May 13 16:56:48 2019 +0300
api: update version number to 1.21.6
Increment version number to reflect timer API specification update and additional features.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/configure.ac b/configure.ac index 83765d9c9..8f9de1489 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ AC_PREREQ([2.5]) ########################################################################## m4_define([odpapi_generation_version], [1]) m4_define([odpapi_major_version], [21]) -m4_define([odpapi_minor_version], [5]) +m4_define([odpapi_minor_version], [6]) m4_define([odpapi_point_version], [0]) m4_define([odpapi_version], [odpapi_generation_version.odpapi_major_version.odpapi_minor_version.odpapi_point_version])
commit 6c34ea307f8d9ab91d4e3d752468996fbf3a9fc4 Author: Petri Savolainen petri.savolainen@nokia.com Date: Thu May 16 15:26:25 2019 +0300
validation: time: test min and hour constants
Check that the new constants are defined.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index 38c0906ba..2113c5461 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -28,6 +28,17 @@ static void time_test_constants(void) { uint64_t ns;
+ CU_ASSERT(ODP_TIME_USEC_IN_NS == 1000); + + ns = ODP_TIME_HOUR_IN_NS; + CU_ASSERT(ns == 60 * ODP_TIME_MIN_IN_NS); + ns = ODP_TIME_MIN_IN_NS; + CU_ASSERT(ns == 60 * ODP_TIME_SEC_IN_NS); + ns = ODP_TIME_SEC_IN_NS; + CU_ASSERT(ns == 1000 * ODP_TIME_MSEC_IN_NS); + ns = ODP_TIME_MSEC_IN_NS; + CU_ASSERT(ns == 1000 * ODP_TIME_USEC_IN_NS); + ns = ODP_TIME_SEC_IN_NS / 1000; CU_ASSERT(ns == ODP_TIME_MSEC_IN_NS); ns /= 1000;
commit ccd90637cf66ef20219719cf636be2e84a93b9ad Author: Petri Savolainen petri.savolainen@nokia.com Date: Thu May 16 15:16:05 2019 +0300
api: time: add defines for minute and hour
Defines for a minute and an hour are useful e.g. when setting timers for a bit longer (background, session lifetime, etc) timeouts.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/include/odp/api/spec/time.h b/include/odp/api/spec/time.h index f79f4a8ac..b96fc077e 100644 --- a/include/odp/api/spec/time.h +++ b/include/odp/api/spec/time.h @@ -22,10 +22,20 @@ extern "C" { * @{ */
-/* Time in nanoseconds */ -#define ODP_TIME_USEC_IN_NS 1000ULL /**< Microsecond in nsec */ -#define ODP_TIME_MSEC_IN_NS 1000000ULL /**< Millisecond in nsec */ -#define ODP_TIME_SEC_IN_NS 1000000000ULL /**< Second in nsec */ +/** A microsecond in nanoseconds */ +#define ODP_TIME_USEC_IN_NS 1000ULL + +/** A millisecond in nanoseconds */ +#define ODP_TIME_MSEC_IN_NS 1000000ULL + +/** A second in nanoseconds */ +#define ODP_TIME_SEC_IN_NS 1000000000ULL + +/** A minute in nanoseconds */ +#define ODP_TIME_MIN_IN_NS 60000000000ULL + +/** An hour in nanoseconds */ +#define ODP_TIME_HOUR_IN_NS 3600000000000ULL
/** * @typedef odp_time_t
commit 22dcfae29a2dc7f0ee00c6d807db1f4424bf9c63 Author: Petri Savolainen petri.savolainen@nokia.com Date: Wed May 15 17:21:19 2019 +0300
validation: timer: add timeout limit tests
Test min/max timeouts with the highest resolution and longest timeout parameters.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c index 56702ae2d..c0527c2e1 100644 --- a/test/validation/api/timer/timer.c +++ b/test/validation/api/timer/timer.c @@ -699,7 +699,7 @@ static void timer_test_sched_queue(void) timer_test_queue_type(ODP_QUEUE_TYPE_SCHED); }
-static void timer_test_odp_timer_cancel(void) +static void timer_test_cancel(void) { odp_pool_t pool; odp_pool_param_t params; @@ -786,6 +786,213 @@ static void timer_test_odp_timer_cancel(void) CU_FAIL_FATAL("Failed to destroy pool"); }
+static void timer_test_tmo_limit(odp_queue_type_t queue_type, + int max_res, int min) +{ + odp_timer_capability_t timer_capa; + odp_pool_t pool; + odp_pool_param_t pool_param; + odp_queue_param_t queue_param; + odp_timer_pool_param_t timer_param; + odp_timer_pool_t timer_pool; + odp_queue_t queue; + odp_timeout_t tmo; + odp_event_t ev; + odp_time_t t1, t2; + uint64_t res_ns, min_tmo, max_tmo; + uint64_t tmo_ns, tmo_tick, diff_ns, max_wait; + int i, ret, num_tmo; + int num = 5; + odp_timer_t timer[num]; + + memset(&timer_capa, 0, sizeof(timer_capa)); + ret = odp_timer_capability(ODP_CLOCK_CPU, &timer_capa); + CU_ASSERT_FATAL(ret == 0); + + if (max_res) { + /* Maximum resolution parameters */ + res_ns = timer_capa.max_res.res_ns; + min_tmo = timer_capa.max_res.min_tmo; + max_tmo = timer_capa.max_res.max_tmo; + } else { + /* Maximum timeout parameters */ + res_ns = timer_capa.max_tmo.res_ns; + min_tmo = timer_capa.max_tmo.min_tmo; + max_tmo = timer_capa.max_tmo.max_tmo; + } + + memset(&timer_param, 0, sizeof(timer_param)); + timer_param.res_ns = res_ns; + timer_param.min_tmo = min_tmo; + timer_param.max_tmo = max_tmo; + timer_param.num_timers = num; + timer_param.clk_src = ODP_CLOCK_CPU; + + timer_pool = odp_timer_pool_create("timer_pool", &timer_param); + if (timer_pool == ODP_TIMER_POOL_INVALID) + CU_FAIL_FATAL("Timer pool create failed"); + + odp_timer_pool_start(); + + 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); + CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); + + odp_queue_param_init(&queue_param); + if (queue_type == ODP_QUEUE_TYPE_SCHED) { + queue_param.type = ODP_QUEUE_TYPE_SCHED; + queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; + } + + queue = odp_queue_create("timeout_queue", &queue_param); + if (queue == ODP_QUEUE_INVALID) + CU_FAIL_FATAL("Queue create failed"); + + if (min) + tmo_ns = min_tmo; + else + tmo_ns = max_tmo; + + tmo_tick = odp_timer_ns_to_tick(timer_pool, tmo_ns); + /* Min_tmo maybe zero. Wait min timeouts at least 20ms + resolution */ + max_wait = (20 * ODP_TIME_MSEC_IN_NS + res_ns + 10 * tmo_ns); + + LOG_DBG("\nTimer pool parameters:\n"); + LOG_DBG(" res_ns %" PRIu64 "\n", timer_param.res_ns); + LOG_DBG(" min_tmo %" PRIu64 "\n", timer_param.min_tmo); + LOG_DBG(" max_tmo %" PRIu64 "\n", timer_param.max_tmo); + LOG_DBG(" tmo_ns %" PRIu64 "\n", tmo_ns); + LOG_DBG(" tmo_tick %" PRIu64 "\n\n", tmo_tick); + + for (i = 0; i < num; i++) { + timer[i] = odp_timer_alloc(timer_pool, queue, NULL); + CU_ASSERT_FATAL(timer[i] != ODP_TIMER_INVALID); + } + + num_tmo = 0; + + for (i = 0; i < num; i++) { + tmo = odp_timeout_alloc(pool); + ev = odp_timeout_to_event(tmo); + + CU_ASSERT(ev != ODP_EVENT_INVALID); + + t1 = odp_time_local(); + ret = odp_timer_set_rel(timer[i], tmo_tick, &ev); + + if (ret == ODP_TIMER_TOOEARLY) + LOG_DBG("Too early %i\n", i); + else if (ret == ODP_TIMER_TOOLATE) + LOG_DBG("Too late %i\n", i); + else if (ret == ODP_TIMER_NOEVENT) + LOG_DBG("No event %i\n", i); + + CU_ASSERT(ret == ODP_TIMER_SUCCESS); + + if (min) { + /* Min timeout - wait for events */ + int break_loop = 0; + + while (1) { + if (queue_type == ODP_QUEUE_TYPE_SCHED) + ev = odp_schedule(NULL, + ODP_SCHED_NO_WAIT); + else + ev = odp_queue_deq(queue); + + t2 = odp_time_local(); + diff_ns = odp_time_diff_ns(t2, t1); + + if (ev != ODP_EVENT_INVALID) { + odp_event_free(ev); + num_tmo++; + break_loop = 1; + LOG_DBG("Timeout [%i]: %" PRIu64 + " nsec\n", i, diff_ns); + continue; + } + + /* Ensure that schedule context is free */ + if (break_loop) + break; + + /* Give up after waiting max wait time */ + if (diff_ns > max_wait) + break; + } + } else { + /* Max timeout - cancel events */ + ev = ODP_EVENT_INVALID; + + ret = odp_timer_cancel(timer[i], &ev); + t2 = odp_time_local(); + diff_ns = odp_time_diff_ns(t2, t1); + + CU_ASSERT(ret == 0); + CU_ASSERT(ev != ODP_EVENT_INVALID); + + if (ev != ODP_EVENT_INVALID) + odp_event_free(ev); + + LOG_DBG("Cancelled [%i]: %" PRIu64 + " nsec\n", i, diff_ns); + } + } + + if (min) + CU_ASSERT(num_tmo == num); + + for (i = 0; i < num; i++) + CU_ASSERT(odp_timer_free(timer[i]) == ODP_EVENT_INVALID); + + odp_timer_pool_destroy(timer_pool); + CU_ASSERT(odp_queue_destroy(queue) == 0); + CU_ASSERT(odp_pool_destroy(pool) == 0); +} + +static void timer_test_max_res_min_tmo_plain(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_PLAIN, 1, 1); +} + +static void timer_test_max_res_min_tmo_sched(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_SCHED, 1, 1); +} + +static void timer_test_max_res_max_tmo_plain(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_PLAIN, 1, 0); +} + +static void timer_test_max_res_max_tmo_sched(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_SCHED, 1, 0); +} + +static void timer_test_max_tmo_min_tmo_plain(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_PLAIN, 0, 1); +} + +static void timer_test_max_tmo_min_tmo_sched(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_SCHED, 0, 1); +} + +static void timer_test_max_tmo_max_tmo_plain(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_PLAIN, 0, 0); +} + +static void timer_test_max_tmo_max_tmo_sched(void) +{ + timer_test_tmo_limit(ODP_QUEUE_TYPE_SCHED, 0, 0); +} + /* Handle a received (timeout) event */ static void handle_tmo(odp_event_t ev, bool stale, uint64_t prev_tick) { @@ -1076,8 +1283,7 @@ static int worker_entrypoint(void *arg TEST_UNUSED) return CU_get_number_of_failures(); }
-/* Timer test case entrypoint */ -static void timer_test_odp_timer_all(void) +static void timer_test_all(void) { int rc; odp_pool_param_t params; @@ -1240,10 +1446,18 @@ odp_testinfo_t timer_suite[] = { ODP_TEST_INFO(timer_test_buf_event_sched), ODP_TEST_INFO(timer_test_pkt_event_plain), ODP_TEST_INFO(timer_test_pkt_event_sched), + ODP_TEST_INFO(timer_test_cancel), + ODP_TEST_INFO(timer_test_max_res_min_tmo_plain), + ODP_TEST_INFO(timer_test_max_res_min_tmo_sched), + ODP_TEST_INFO(timer_test_max_res_max_tmo_plain), + ODP_TEST_INFO(timer_test_max_res_max_tmo_sched), + ODP_TEST_INFO(timer_test_max_tmo_min_tmo_plain), + ODP_TEST_INFO(timer_test_max_tmo_min_tmo_sched), + ODP_TEST_INFO(timer_test_max_tmo_max_tmo_plain), + ODP_TEST_INFO(timer_test_max_tmo_max_tmo_sched), ODP_TEST_INFO(timer_test_plain_queue), ODP_TEST_INFO(timer_test_sched_queue), - ODP_TEST_INFO(timer_test_odp_timer_cancel), - ODP_TEST_INFO(timer_test_odp_timer_all), + ODP_TEST_INFO(timer_test_all), ODP_TEST_INFO_NULL, };
commit 4f0e6037a7037c0879062f2b1ead0503f45ae623 Author: Petri Savolainen petri.savolainen@nokia.com Date: Wed May 15 17:16:50 2019 +0300
linux-gen: timer: add warm up period
Added warm up period into posix timer pool startup to avoid the first timeout to slip. Otherwise, timer pthread receives the first signal after about 15ms and first timeout of the pool slips.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c index 6cb8c9b39..8e98d51ac 100644 --- a/platform/linux-generic/odp_timer.c +++ b/platform/linux-generic/odp_timer.c @@ -195,9 +195,11 @@ typedef struct timer_pool_s { odp_shm_t shm; timer_t timerid; int notify_overrun; - pthread_t timer_thread; /* pthread_t of timer thread */ - pid_t timer_thread_id; /* gettid() for timer thread */ - int timer_thread_exit; /* request to exit for timer thread */ + pthread_t thr_pthread; /* pthread_t of timer thread */ + pid_t thr_pid; /* gettid() for timer thread */ + int thr_warm_up; /* number of warm up rounds */ + odp_atomic_u32_t thr_ready; /* thread ready from warm up */ + int thr_exit; /* request to exit for timer thread */ } timer_pool_t;
/* Timer pool index must fit into 8 bits with one index value reserved to @@ -381,8 +383,8 @@ static void stop_timer_thread(timer_pool_t *tp) int ret;
ODP_DBG("stop\n"); - tp->timer_thread_exit = 1; - ret = pthread_join(tp->timer_thread, NULL); + tp->thr_exit = 1; + ret = pthread_join(tp->thr_pthread, NULL); if (ret != 0) ODP_ABORT("unable to join thread, err %d\n", ret); } @@ -954,26 +956,41 @@ static void *timer_thread(void *arg) int ret; struct timespec tmo; siginfo_t si; + int warm_up = tp->thr_warm_up; + int num = 0;
- tp->timer_thread_id = (pid_t)syscall(SYS_gettid); - - tmo.tv_sec = 0; + tmo.tv_sec = 0; tmo.tv_nsec = ODP_TIME_MSEC_IN_NS * 100;
+ /* Unblock sigalarm in this thread */ sigemptyset(&sigset); - /* unblock sigalarm in this thread */ sigprocmask(SIG_BLOCK, &sigset, NULL); - sigaddset(&sigset, SIGALRM);
+ /* Signal that this thread has started */ + odp_mb_full(); + tp->thr_pid = (pid_t)syscall(SYS_gettid); + odp_mb_full(); + while (1) { ret = sigtimedwait(&sigset, &si, &tmo); - if (tp->timer_thread_exit) { - tp->timer_thread_id = 0; + + if (tp->thr_exit) { + tp->thr_pid = 0; return NULL; } - if (ret > 0) - timer_notify(tp); + + if (ret <= 0) + continue; + + timer_notify(tp); + + if (num < warm_up) { + num++; + + if (num == warm_up) + odp_atomic_store_rel_u32(&tp->thr_ready, 1); + } }
return NULL; @@ -1067,30 +1084,36 @@ static void itimer_init(timer_pool_t *tp) ODP_DBG("Creating POSIX timer for timer pool %s, period %" PRIu64" ns\n", tp->name, tp->param.res_ns);
- tp->timer_thread_id = 0; - ret = pthread_create(&tp->timer_thread, NULL, timer_thread, tp); + res = tp->param.res_ns; + sec = res / ODP_TIME_SEC_IN_NS; + nsec = res - sec * ODP_TIME_SEC_IN_NS; + + tp->thr_pid = 0; + tp->thr_warm_up = 1; + + /* 20ms warm up */ + if (res < (20 * ODP_TIME_MSEC_IN_NS)) + tp->thr_warm_up = (20 * ODP_TIME_MSEC_IN_NS) / res; + + odp_atomic_init_u32(&tp->thr_ready, 0); + ret = pthread_create(&tp->thr_pthread, NULL, timer_thread, tp); if (ret) ODP_ABORT("unable to create timer thread\n");
- /* wait thread set tp->timer_thread_id */ - do { + /* wait thread set tp->thr_pid */ + while (tp->thr_pid == 0) sched_yield(); - } while (tp->timer_thread_id == 0);
memset(&sigev, 0, sizeof(sigev)); sigev.sigev_notify = SIGEV_THREAD_ID; sigev.sigev_value.sival_ptr = tp; - sigev._sigev_un._tid = tp->timer_thread_id; + sigev._sigev_un._tid = tp->thr_pid; sigev.sigev_signo = SIGALRM;
if (timer_create(CLOCK_MONOTONIC, &sigev, &tp->timerid)) ODP_ABORT("timer_create() returned error %s\n", strerror(errno));
- res = tp->param.res_ns; - sec = res / ODP_TIME_SEC_IN_NS; - nsec = res - sec * ODP_TIME_SEC_IN_NS; - memset(&ispec, 0, sizeof(ispec)); ispec.it_interval.tv_sec = (time_t)sec; ispec.it_interval.tv_nsec = (long)nsec; @@ -1100,6 +1123,11 @@ static void itimer_init(timer_pool_t *tp) if (timer_settime(tp->timerid, 0, &ispec, NULL)) ODP_ABORT("timer_settime() returned error %s\n", strerror(errno)); + + /* Wait response from timer thread that warm up signals have been + * processed. Warm up helps avoiding overrun on the first timeout. */ + while (odp_atomic_load_acq_u32(&tp->thr_ready) == 0) + sched_yield(); }
static void itimer_fini(timer_pool_t *tp)
commit 47fae268aef777b8d523dca43d0b50f8139bc8cf Author: Petri Savolainen petri.savolainen@nokia.com Date: Tue May 14 16:57:54 2019 +0300
validation: timer: add capability test
Add new test case for timer and resolution capability.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c index 1faef4e64..56702ae2d 100644 --- a/test/validation/api/timer/timer.c +++ b/test/validation/api/timer/timer.c @@ -181,6 +181,43 @@ static int timer_global_term(odp_instance_t inst) return 0; }
+static void timer_test_capa(void) +{ + odp_timer_capability_t capa; + odp_timer_res_capability_t res_capa; + int ret; + + memset(&capa, 0, sizeof(capa)); + ret = odp_timer_capability(ODP_CLOCK_CPU, &capa); + CU_ASSERT_FATAL(ret == 0); + + CU_ASSERT(capa.highest_res_ns == capa.max_res.res_ns); + CU_ASSERT(capa.max_res.res_ns < capa.max_res.max_tmo); + CU_ASSERT(capa.max_res.min_tmo < capa.max_res.max_tmo); + CU_ASSERT(capa.max_tmo.res_ns < capa.max_tmo.max_tmo); + CU_ASSERT(capa.max_tmo.min_tmo < capa.max_tmo.max_tmo); + + /* Set max resolution */ + memset(&res_capa, 0, sizeof(res_capa)); + res_capa.res_ns = capa.max_res.res_ns; + + ret = odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa); + CU_ASSERT_FATAL(ret == 0); + CU_ASSERT(res_capa.res_ns == capa.max_res.res_ns); + CU_ASSERT(res_capa.min_tmo == capa.max_res.min_tmo); + CU_ASSERT(res_capa.max_tmo == capa.max_res.max_tmo); + + /* Set max timeout */ + memset(&res_capa, 0, sizeof(res_capa)); + res_capa.max_tmo = capa.max_tmo.max_tmo; + + ret = odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa); + CU_ASSERT_FATAL(ret == 0); + CU_ASSERT(res_capa.max_tmo == capa.max_tmo.max_tmo); + CU_ASSERT(res_capa.min_tmo == capa.max_tmo.min_tmo); + CU_ASSERT(res_capa.res_ns == capa.max_tmo.res_ns); +} + static void timer_test_timeout_pool_alloc(void) { odp_pool_t pool; @@ -1193,6 +1230,7 @@ static void timer_test_odp_timer_all(void) }
odp_testinfo_t timer_suite[] = { + ODP_TEST_INFO(timer_test_capa), ODP_TEST_INFO(timer_test_timeout_pool_alloc), ODP_TEST_INFO(timer_test_timeout_pool_free), ODP_TEST_INFO(timer_pool_create_destroy),
commit 2600af0ade3c254ba00a935a38647d6d15611586 Author: Petri Savolainen petri.savolainen@nokia.com Date: Tue May 14 16:39:02 2019 +0300
validation: timer: use resolution capability
Limit min/max timeout values according to the used resolution. Most tests use the same resolution and min/max timeout settings.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c index ddccec2b1..1faef4e64 100644 --- a/test/validation/api/timer/timer.c +++ b/test/validation/api/timer/timer.c @@ -31,9 +31,7 @@ #define EXTRA_TIMERS 256
#define NAME "timer_pool" -#define RES (10 * ODP_TIME_MSEC_IN_NS / 3) -#define MIN_TMO (10 * ODP_TIME_MSEC_IN_NS / 3) -#define MAX_TMO (1000000 * ODP_TIME_MSEC_IN_NS) +#define THREE_POINT_THREE_MSEC (10 * ODP_TIME_MSEC_IN_NS / 3) #define USER_PTR ((void *)0xdead) #define TICK_INVALID (~(uint64_t)0)
@@ -46,19 +44,32 @@ struct test_timer { };
typedef struct { + /* Default resolution / timeout parameters */ + struct { + uint64_t res_ns; + uint64_t min_tmo; + uint64_t max_tmo; + } param; + /* Timeout pool handle used by all threads */ odp_pool_t tbp; + /* Timer pool handle used by all threads */ odp_timer_pool_t tp; + /* Barrier for thread synchronization */ odp_barrier_t test_barrier; + /* Count of timeouts delivered too late */ odp_atomic_u32_t ndelivtoolate; + /* Sum of all allocated timers from all threads. Thread-local * caches may make this number lower than the capacity of the pool */ odp_atomic_u32_t timers_allocated; + /* Number of timers allocated per thread */ uint32_t timers_per_thread; + } global_shared_mem_t;
static global_shared_mem_t *global_mem; @@ -68,6 +79,10 @@ static int timer_global_init(odp_instance_t *inst) odp_shm_t global_shm; odp_init_t init_param; odph_helper_options_t helper_options; + odp_timer_capability_t capa; + odp_timer_res_capability_t res_capa; + uint64_t res_ns, min_tmo, max_tmo; + unsigned int range;
if (odph_options(&helper_options)) { fprintf(stderr, "error: odph_options() failed.\n"); @@ -100,6 +115,46 @@ static int timer_global_init(odp_instance_t *inst) /* Configure scheduler */ odp_schedule_config(NULL);
+ memset(&capa, 0, sizeof(capa)); + if (odp_timer_capability(ODP_CLOCK_CPU, &capa)) { + fprintf(stderr, "Timer capability failed\n"); + return -1; + } + + /* By default 20 msec resolution */ + res_ns = 20 * ODP_TIME_MSEC_IN_NS; + if (res_ns < capa.max_res.res_ns) + res_ns = capa.max_res.res_ns; + + memset(&res_capa, 0, sizeof(res_capa)); + res_capa.res_ns = res_ns; + + if (odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa)) { + fprintf(stderr, "Timer resolution capability failed\n"); + return -1; + } + + /* Try to keep min timeout error margin within +-20% */ + min_tmo = 5 * res_ns; + if (min_tmo < res_capa.min_tmo) + min_tmo = res_capa.min_tmo; + + /* Max 1 hour */ + max_tmo = 3600 * ODP_TIME_SEC_IN_NS; + if (max_tmo > res_capa.max_tmo) + max_tmo = res_capa.max_tmo; + + range = (RANGE_MS * 1000) + THREE_POINT_THREE_MSEC; + if ((max_tmo - min_tmo) < range) { + fprintf(stderr, "Validation test needs %u msec range\n", range); + return -1; + } + + /* Default parameters for test cases */ + global_mem->param.res_ns = res_ns; + global_mem->param.min_tmo = min_tmo; + global_mem->param.max_tmo = max_tmo; + return 0; }
@@ -213,25 +268,19 @@ static void timer_test_timeout_pool_free(void)
static void timer_pool_create_destroy(void) { - odp_timer_capability_t timer_capa; odp_timer_pool_param_t tparam; odp_timer_pool_info_t info; odp_timer_pool_t tp[2]; odp_timer_t tim; odp_queue_t queue; - uint64_t res_ns;
queue = odp_queue_create("timer_queue", NULL); CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
- CU_ASSERT_FATAL(odp_timer_capability(ODP_CLOCK_CPU, &timer_capa) == 0); - - res_ns = 10 * timer_capa.highest_res_ns; - memset(&tparam, 0, sizeof(odp_timer_pool_param_t)); - tparam.res_ns = res_ns; - tparam.min_tmo = 5 * res_ns; - tparam.max_tmo = 10000 * tparam.min_tmo; + tparam.res_ns = global_mem->param.res_ns; + tparam.min_tmo = global_mem->param.min_tmo; + tparam.max_tmo = global_mem->param.max_tmo; tparam.num_timers = 100; tparam.priv = 0; tparam.clk_src = ODP_CLOCK_CPU; @@ -290,7 +339,6 @@ static void timer_test_event_type(odp_queue_type_t queue_type, odp_pool_t pool; odp_pool_param_t pool_param; odp_queue_param_t queue_param; - odp_timer_capability_t timer_capa; odp_timer_pool_param_t timer_param; odp_timer_pool_t timer_pool; odp_queue_t queue; @@ -299,24 +347,16 @@ static void timer_test_event_type(odp_queue_type_t queue_type, odp_packet_t pkt; odp_event_t ev; odp_time_t t1, t2; - uint64_t res_ns, period_ns, period_tick, duration_ns; + uint64_t period_ns, period_tick, duration_ns; int i, ret, num_tmo; int num = 5; odp_timer_t timer[num];
- if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) - CU_FAIL_FATAL("Timer capability failed") - - res_ns = 20 * ODP_TIME_MSEC_IN_NS; - - if (timer_capa.highest_res_ns > res_ns) - res_ns = timer_capa.highest_res_ns; - memset(&timer_param, 0, sizeof(timer_param)); - timer_param.res_ns = res_ns; - timer_param.min_tmo = 5 * res_ns; - period_ns = 2 * timer_param.min_tmo; - timer_param.max_tmo = 100 * period_ns; + timer_param.res_ns = global_mem->param.res_ns; + timer_param.min_tmo = global_mem->param.min_tmo; + period_ns = 2 * global_mem->param.min_tmo; + timer_param.max_tmo = global_mem->param.max_tmo; timer_param.num_timers = num; timer_param.clk_src = ODP_CLOCK_CPU;
@@ -478,7 +518,6 @@ static void timer_test_queue_type(odp_queue_type_t queue_type) uint64_t res_ns, period_ns, period_tick, test_period; uint64_t diff_period, diff_test; odp_pool_param_t params; - odp_timer_capability_t timer_capa; odp_time_t t0, t1, t2;
odp_pool_param_init(¶ms); @@ -488,17 +527,11 @@ static void timer_test_queue_type(odp_queue_type_t queue_type) pool = odp_pool_create("timeout_pool", ¶ms); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
- if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) - CU_FAIL_FATAL("Timer capability failed") - - res_ns = 20 * ODP_TIME_MSEC_IN_NS; + res_ns = global_mem->param.res_ns;
- if (timer_capa.highest_res_ns > res_ns) - res_ns = timer_capa.highest_res_ns; - - tparam.res_ns = res_ns; - tparam.min_tmo = 5 * res_ns; - tparam.max_tmo = 10000 * tparam.min_tmo; + tparam.res_ns = global_mem->param.res_ns; + tparam.min_tmo = global_mem->param.min_tmo; + tparam.max_tmo = global_mem->param.max_tmo; tparam.num_timers = num + 1; tparam.priv = 0; tparam.clk_src = ODP_CLOCK_CPU; @@ -641,7 +674,6 @@ static void timer_test_odp_timer_cancel(void) odp_timeout_t tmo; odp_timer_set_t rc; uint64_t tick; - odp_timer_capability_t timer_capa;
odp_pool_param_init(¶ms); params.type = ODP_POOL_TIMEOUT; @@ -652,13 +684,9 @@ static void timer_test_odp_timer_cancel(void) if (pool == ODP_POOL_INVALID) CU_FAIL_FATAL("Timeout pool create failed");
- if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) - CU_FAIL_FATAL("Get timer capability failed") - - tparam.res_ns = MAX(100 * ODP_TIME_MSEC_IN_NS, - timer_capa.highest_res_ns); - tparam.min_tmo = 1 * ODP_TIME_SEC_IN_NS; - tparam.max_tmo = 10 * ODP_TIME_SEC_IN_NS; + tparam.res_ns = global_mem->param.res_ns; + tparam.min_tmo = global_mem->param.min_tmo; + tparam.max_tmo = global_mem->param.max_tmo; tparam.num_timers = 1; tparam.priv = 0; tparam.clk_src = ODP_CLOCK_CPU; @@ -682,7 +710,7 @@ static void timer_test_odp_timer_cancel(void) if (ev == ODP_EVENT_INVALID) CU_FAIL_FATAL("Failed to allocate timeout");
- tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC_IN_NS); + tick = odp_timer_ns_to_tick(tp, tparam.max_tmo / 2);
rc = odp_timer_set_rel(tim, tick, &ev); if (rc != ODP_TIMER_SUCCESS) @@ -826,6 +854,7 @@ static int worker_entrypoint(void *arg TEST_UNUSED) odp_timer_pool_t tp = global_mem->tp; odp_pool_t tbp = global_mem->tbp; uint32_t num_timers = global_mem->timers_per_thread; + uint64_t min_tmo = global_mem->param.min_tmo;
queue = odp_queue_create("timer_queue", NULL); if (queue == ODP_QUEUE_INVALID) @@ -863,7 +892,8 @@ static int worker_entrypoint(void *arg TEST_UNUSED) /* Initial set all timers with a random expiration time */ nset = 0; for (i = 0; i < allocated; i++) { - nsec = MIN_TMO + (rand_r(&seed) % RANGE_MS) * 1000000ULL; + nsec = min_tmo + THREE_POINT_THREE_MSEC + + (rand_r(&seed) % RANGE_MS) * 1000000ULL; tck = odp_timer_current_tick(tp) + odp_timer_ns_to_tick(tp, nsec); timer_rc = odp_timer_set_abs(tt[i].tim, tck, &tt[i].ev); @@ -918,7 +948,7 @@ static int worker_entrypoint(void *arg TEST_UNUSED) /* Timer active => reset */ nreset++;
- nsec = MIN_TMO + + nsec = min_tmo + THREE_POINT_THREE_MSEC + (rand_r(&seed) % RANGE_MS) * 1000000ULL; tck = odp_timer_ns_to_tick(tp, nsec);
@@ -1018,7 +1048,7 @@ static void timer_test_odp_timer_all(void) odp_cpumask_t unused; odp_timer_pool_info_t tpinfo; uint64_t ns, tick, ns2; - uint64_t resolution_ns; + uint64_t res_ns, min_tmo, max_tmo; uint32_t timers_allocated; pthrd_arg thrdarg; odp_pool_capability_t pool_capa; @@ -1065,10 +1095,13 @@ static void timer_test_odp_timer_all(void) tbp = global_mem->tbp;
/* Create a timer pool */ - resolution_ns = MAX(RES, timer_capa.highest_res_ns); - tparam.res_ns = resolution_ns; - tparam.min_tmo = MIN_TMO; - tparam.max_tmo = MAX_TMO; + res_ns = global_mem->param.res_ns; + max_tmo = global_mem->param.max_tmo; + min_tmo = global_mem->param.min_tmo; + + tparam.res_ns = res_ns; + tparam.min_tmo = min_tmo; + tparam.max_tmo = max_tmo; tparam.num_timers = num_timers; tparam.priv = 0; tparam.clk_src = ODP_CLOCK_CPU; @@ -1083,10 +1116,9 @@ static void timer_test_odp_timer_all(void) if (odp_timer_pool_info(tp, &tpinfo) != 0) CU_FAIL("odp_timer_pool_info"); CU_ASSERT(strcmp(tpinfo.name, NAME) == 0); - CU_ASSERT(tpinfo.param.res_ns == MAX(RES, - timer_capa.highest_res_ns)); - CU_ASSERT(tpinfo.param.min_tmo == MIN_TMO); - CU_ASSERT(tpinfo.param.max_tmo == MAX_TMO); + CU_ASSERT(tpinfo.param.res_ns == res_ns); + CU_ASSERT(tpinfo.param.min_tmo == min_tmo); + CU_ASSERT(tpinfo.param.max_tmo == max_tmo); CU_ASSERT(strcmp(tpinfo.name, NAME) == 0);
LOG_DBG("Timer pool handle: %" PRIu64 "\n", odp_timer_pool_to_u64(tp)); @@ -1106,17 +1138,17 @@ static void timer_test_odp_timer_all(void) ns2 = odp_timer_tick_to_ns(tp, tick); CU_ASSERT(ns2 == 0);
- for (ns = resolution_ns; ns < MAX_TMO; ns += resolution_ns) { + for (ns = res_ns; ns < max_tmo; ns += res_ns) { tick = odp_timer_ns_to_tick(tp, ns); ns2 = odp_timer_tick_to_ns(tp, tick);
- if (ns2 < ns - resolution_ns) { + if (ns2 < ns - res_ns) { LOG_DBG("FAIL ns:%" PRIu64 " tick:%" PRIu64 " ns2:%" PRIu64 "\n", ns, tick, ns2); CU_FAIL("tick conversion: nsec too small\n"); }
- if (ns2 > ns + resolution_ns) { + if (ns2 > ns + res_ns) { LOG_DBG("FAIL ns:%" PRIu64 " tick:%" PRIu64 " ns2:%" PRIu64 "\n", ns, tick, ns2); CU_FAIL("tick conversion: nsec too large\n");
commit 6280e54ea0a69276f3e1cbadd981f28dd2fb253a Author: Petri Savolainen petri.savolainen@nokia.com Date: Tue May 14 14:08:14 2019 +0300
linux-gen: timer: implement new capability features
Timer implementation does not have limits to timeout values.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c index 6446b1c91..6cb8c9b39 100644 --- a/platform/linux-generic/odp_timer.c +++ b/platform/linux-generic/odp_timer.c @@ -70,6 +70,9 @@ * for checking the freshness of received timeouts */ #define TMO_INACTIVE ((uint64_t)0x8000000000000000)
+/* Max timeout in capability. One year in nsec (0x0070 09D3 2DA3 0000). */ +#define MAX_TMO_NSEC (365 * 24 * 3600 * ODP_TIME_SEC_IN_NS) + /****************************************************************************** * Mutual exclusion in the absence of CAS16 *****************************************************************************/ @@ -1114,18 +1117,49 @@ static void itimer_fini(timer_pool_t *tp) int odp_timer_capability(odp_timer_clk_src_t clk_src, odp_timer_capability_t *capa) { - int ret = 0; + if (clk_src != ODP_CLOCK_CPU) { + ODP_ERR("Only CPU clock source supported\n"); + return -1; + }
- if (clk_src == ODP_CLOCK_CPU) { - capa->max_pools_combined = MAX_TIMER_POOLS; - capa->max_pools = MAX_TIMER_POOLS; - capa->max_timers = 0; - capa->highest_res_ns = timer_global->highest_res_ns; - } else { - ODP_ERR("ODP timer system doesn't support external clock source currently\n"); - ret = -1; + memset(capa, 0, sizeof(odp_timer_capability_t)); + + capa->max_pools_combined = MAX_TIMER_POOLS; + capa->max_pools = MAX_TIMER_POOLS; + capa->max_timers = 0; + capa->highest_res_ns = timer_global->highest_res_ns; + capa->max_res.res_ns = timer_global->highest_res_ns; + capa->max_res.min_tmo = 0; + capa->max_res.max_tmo = MAX_TMO_NSEC; + capa->max_tmo.res_ns = timer_global->highest_res_ns; + capa->max_tmo.min_tmo = 0; + capa->max_tmo.max_tmo = MAX_TMO_NSEC; + + return 0; +} + +int odp_timer_res_capability(odp_timer_clk_src_t clk_src, + odp_timer_res_capability_t *res_capa) +{ + if (clk_src != ODP_CLOCK_CPU) { + ODP_ERR("Only CPU clock source supported\n"); + return -1; + } + + if (res_capa->min_tmo) { + ODP_ERR("Only res_ns or max_tmo based quaries supported\n"); + return -1; } - return ret; + + if (res_capa->res_ns) { + res_capa->min_tmo = 0; + res_capa->max_tmo = MAX_TMO_NSEC; + } else { /* max_tmo */ + res_capa->min_tmo = 0; + res_capa->res_ns = timer_global->highest_res_ns; + } + + return 0; }
odp_timer_pool_t odp_timer_pool_create(const char *name,
commit b78412a08ad0435ace4d2980a38fa44b1fddbf96 Author: Petri Savolainen petri.savolainen@nokia.com Date: Wed May 8 17:15:56 2019 +0300
api: timer: add resolution capability
Typically, timer implementation needs to trade-off between highest resolution and longest timeout. Add new capability information and function to check limits between resolution and maximum timeout length.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/include/odp/api/spec/timer.h b/include/odp/api/spec/timer.h index c2bf942dc..0e06a9030 100644 --- a/include/odp/api/spec/timer.h +++ b/include/odp/api/spec/timer.h @@ -135,6 +135,21 @@ typedef struct {
} odp_timer_pool_param_t;
+/** + * Timer resolution capability + */ +typedef struct { + /** Timeout resolution in nanoseconds */ + uint64_t res_ns; + + /** Minimum relative timeout in nanoseconds */ + uint64_t min_tmo; + + /** Maximum relative timeout in nanoseconds */ + uint64_t max_tmo; + +} odp_timer_res_capability_t; + /** * Timer capability */ @@ -160,8 +175,35 @@ typedef struct { * This defines the highest resolution supported by a timer. * It's the minimum valid value for 'res_ns' timer pool * parameter. + * + * This value is equal to 'max_res.res_ns' capability. */ uint64_t highest_res_ns; + + /** + * Maximum resolution + * + * This defines the highest resolution supported by a timer, with + * limits to min/max timeout values. The highest resolution for a timer + * pool is defined by 'max_res.res_ns', therefore it's the minimum value + * for 'res_ns' timer pool parameter. When this resolution is used: + * - 'min_tmo' parameter value must be in minimum 'max_res.min_tmo' + * - 'max_tmo' parameter value must be in maximum 'max_res.max_tmo' + */ + odp_timer_res_capability_t max_res; + + /** + * Maximum timeout length + * + * This defines the maximum relative timeout value supported by a timer, + * with limits to min timeout and max resolution values. The maximum + * value for 'max_tmo' timer pool parameter is defined by + * 'max_tmo.max_tmo'. When this max timeout value is used: + * - 'min_tmo' parameter value must be in minimum 'max_tmo.min_tmo' + * - 'res_ns' parameter value must be in minimum 'max_tmo.res_ns' + */ + odp_timer_res_capability_t max_tmo; + } odp_timer_capability_t;
/** @@ -178,6 +220,28 @@ typedef struct { int odp_timer_capability(odp_timer_clk_src_t clk_src, odp_timer_capability_t *capa);
+/** + * Timer resolution capability + * + * This function fills in capability limits for timer pool resolution and + * min/max timeout values, based on either resolution or maximum timeout. + * Set the required value to 'res_ns' or 'max_tmo', and set other fields to + * zero. A successful call fills in the other two fields. The call returns + * a failure, if the user defined value ('res_ns' or 'max_tmo)' exceeds + * capability limits. Outputted values are minimums for 'res_ns' and 'min_tmo', + * and a maximum for 'max_tmo'. + * + * @param clk_src Clock source for timers + * @param[in,out] res_capa Resolution capability pointer for input/output. + * Set either 'res_ns' or 'max_tmo', a successful call + * fills in other fields. + * + * @retval 0 on success + * @retval <0 on failure + */ +int odp_timer_res_capability(odp_timer_clk_src_t clk_src, + odp_timer_res_capability_t *res_capa); + /** * Create a timer pool *
commit 5422332ff596b8cef9d5518b7bff6ab9b4b38b09 Author: Petri Savolainen petri.savolainen@nokia.com Date: Mon May 13 16:52:22 2019 +0300
validation: timer: test pkt and buf event types
Test that also buffer and packet type events can be used as timeout events.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c index 51caed7a5..ddccec2b1 100644 --- a/test/validation/api/timer/timer.c +++ b/test/validation/api/timer/timer.c @@ -284,6 +284,184 @@ static void timer_pool_create_destroy(void) CU_ASSERT(odp_queue_destroy(queue) == 0); }
+static void timer_test_event_type(odp_queue_type_t queue_type, + odp_event_type_t event_type) +{ + odp_pool_t pool; + odp_pool_param_t pool_param; + odp_queue_param_t queue_param; + odp_timer_capability_t timer_capa; + odp_timer_pool_param_t timer_param; + odp_timer_pool_t timer_pool; + odp_queue_t queue; + odp_timeout_t tmo; + odp_buffer_t buf; + odp_packet_t pkt; + odp_event_t ev; + odp_time_t t1, t2; + uint64_t res_ns, period_ns, period_tick, duration_ns; + int i, ret, num_tmo; + int num = 5; + odp_timer_t timer[num]; + + if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) + CU_FAIL_FATAL("Timer capability failed") + + res_ns = 20 * ODP_TIME_MSEC_IN_NS; + + if (timer_capa.highest_res_ns > res_ns) + res_ns = timer_capa.highest_res_ns; + + memset(&timer_param, 0, sizeof(timer_param)); + timer_param.res_ns = res_ns; + timer_param.min_tmo = 5 * res_ns; + period_ns = 2 * timer_param.min_tmo; + timer_param.max_tmo = 100 * period_ns; + timer_param.num_timers = num; + timer_param.clk_src = ODP_CLOCK_CPU; + + timer_pool = odp_timer_pool_create("timer_pool", &timer_param); + if (timer_pool == ODP_TIMER_POOL_INVALID) + CU_FAIL_FATAL("Timer pool create failed"); + + odp_timer_pool_start(); + + odp_pool_param_init(&pool_param); + + if (event_type == ODP_EVENT_BUFFER) { + pool_param.type = ODP_POOL_BUFFER; + pool_param.buf.num = num; + } else if (event_type == ODP_EVENT_PACKET) { + pool_param.type = ODP_POOL_PACKET; + pool_param.pkt.num = num; + } else if (event_type == ODP_EVENT_TIMEOUT) { + pool_param.type = ODP_POOL_TIMEOUT; + pool_param.tmo.num = num; + } else { + CU_FAIL("Bad event_type"); + return; + } + + pool = odp_pool_create("timeout_pool", &pool_param); + CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); + + odp_queue_param_init(&queue_param); + if (queue_type == ODP_QUEUE_TYPE_SCHED) { + queue_param.type = ODP_QUEUE_TYPE_SCHED; + queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; + } + + queue = odp_queue_create("timeout_queue", &queue_param); + if (queue == ODP_QUEUE_INVALID) + CU_FAIL_FATAL("Queue create failed"); + + period_tick = odp_timer_ns_to_tick(timer_pool, period_ns); + duration_ns = num * period_ns; + + LOG_DBG("\nTimer pool parameters:\n"); + LOG_DBG(" res_ns %" PRIu64 "\n", timer_param.res_ns); + LOG_DBG(" min_tmo %" PRIu64 "\n", timer_param.min_tmo); + LOG_DBG(" max_tmo %" PRIu64 "\n", timer_param.max_tmo); + LOG_DBG(" period_ns %" PRIu64 "\n", period_ns); + LOG_DBG(" period_tick %" PRIu64 "\n", period_tick); + LOG_DBG(" duration_ns %" PRIu64 "\n\n", duration_ns); + + for (i = 0; i < num; i++) { + if (event_type == ODP_EVENT_BUFFER) { + buf = odp_buffer_alloc(pool); + ev = odp_buffer_to_event(buf); + } else if (event_type == ODP_EVENT_PACKET) { + pkt = odp_packet_alloc(pool, 10); + ev = odp_packet_to_event(pkt); + } else { + tmo = odp_timeout_alloc(pool); + ev = odp_timeout_to_event(tmo); + } + + CU_ASSERT(ev != ODP_EVENT_INVALID); + + timer[i] = odp_timer_alloc(timer_pool, queue, NULL); + CU_ASSERT_FATAL(timer[i] != ODP_TIMER_INVALID); + + ret = odp_timer_set_rel(timer[i], (i + 1) * period_tick, &ev); + + if (ret == ODP_TIMER_TOOEARLY) + LOG_DBG("Too early %i\n", i); + else if (ret == ODP_TIMER_TOOLATE) + LOG_DBG("Too late %i\n", i); + else if (ret == ODP_TIMER_NOEVENT) + LOG_DBG("No event %i\n", i); + + CU_ASSERT(ret == ODP_TIMER_SUCCESS); + } + + ev = ODP_EVENT_INVALID; + num_tmo = 0; + t1 = odp_time_local(); + + /* Wait for timers. Make sure that scheduler context is not hold when + * exiting the loop. */ + do { + if (queue_type == ODP_QUEUE_TYPE_SCHED) + ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT); + else + ev = odp_queue_deq(queue); + + if (ev == ODP_EVENT_INVALID) { + t2 = odp_time_local(); + if (odp_time_diff_ns(t2, t1) > (10 * duration_ns)) + break; + + continue; + } + + CU_ASSERT(odp_event_type(ev) == event_type); + + odp_event_free(ev); + num_tmo++; + + } while (num_tmo < num || ev != ODP_EVENT_INVALID); + + CU_ASSERT(num_tmo == num); + + for (i = 0; i < num; i++) + CU_ASSERT(odp_timer_free(timer[i]) == ODP_EVENT_INVALID); + + odp_timer_pool_destroy(timer_pool); + CU_ASSERT(odp_queue_destroy(queue) == 0); + CU_ASSERT(odp_pool_destroy(pool) == 0); +} + +static void timer_test_tmo_event_plain(void) +{ + timer_test_event_type(ODP_QUEUE_TYPE_PLAIN, ODP_EVENT_TIMEOUT); +} + +static void timer_test_tmo_event_sched(void) +{ + timer_test_event_type(ODP_QUEUE_TYPE_SCHED, ODP_EVENT_TIMEOUT); +} + +static void timer_test_buf_event_plain(void) +{ + timer_test_event_type(ODP_QUEUE_TYPE_PLAIN, ODP_EVENT_BUFFER); +} + +static void timer_test_buf_event_sched(void) +{ + timer_test_event_type(ODP_QUEUE_TYPE_SCHED, ODP_EVENT_BUFFER); +} + +static void timer_test_pkt_event_plain(void) +{ + timer_test_event_type(ODP_QUEUE_TYPE_PLAIN, ODP_EVENT_PACKET); +} + +static void timer_test_pkt_event_sched(void) +{ + timer_test_event_type(ODP_QUEUE_TYPE_SCHED, ODP_EVENT_PACKET); +} + static void timer_test_queue_type(odp_queue_type_t queue_type) { odp_pool_t pool; @@ -986,6 +1164,12 @@ odp_testinfo_t timer_suite[] = { ODP_TEST_INFO(timer_test_timeout_pool_alloc), ODP_TEST_INFO(timer_test_timeout_pool_free), ODP_TEST_INFO(timer_pool_create_destroy), + ODP_TEST_INFO(timer_test_tmo_event_plain), + ODP_TEST_INFO(timer_test_tmo_event_sched), + ODP_TEST_INFO(timer_test_buf_event_plain), + ODP_TEST_INFO(timer_test_buf_event_sched), + ODP_TEST_INFO(timer_test_pkt_event_plain), + ODP_TEST_INFO(timer_test_pkt_event_sched), ODP_TEST_INFO(timer_test_plain_queue), ODP_TEST_INFO(timer_test_sched_queue), ODP_TEST_INFO(timer_test_odp_timer_cancel),
commit 9eeb94e6d03923a67779314c62e32e410e1272d8 Author: Petri Savolainen petri.savolainen@nokia.com Date: Mon May 13 14:06:22 2019 +0300
api: timer: documentation style clean up
Clean up stylistic issues in documentation: indentation, variable naming, new lines, etc.
API functionality or wording not changed.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/include/odp/api/spec/timer.h b/include/odp/api/spec/timer.h index 1ad7ae4f6..c2bf942dc 100644 --- a/include/odp/api/spec/timer.h +++ b/include/odp/api/spec/timer.h @@ -69,26 +69,29 @@ typedef enum { * Return values of timer set calls. */ typedef enum { -/** - * Timer set operation succeeded - */ + /** + * Timer set operation succeeded + */ ODP_TIMER_SUCCESS = 0, -/** - * Timer set operation failed, expiration too early. - * Either retry with a later expiration time or process the timeout - * immediately. */ + + /** + * Timer set operation failed, expiration too early. + * Either retry with a later expiration time or process the timeout + * immediately. */ ODP_TIMER_TOOEARLY = -1,
-/** - * Timer set operation failed, expiration too late. - * Truncate the expiration time against the maximum timeout for the - * timer pool. */ + /** + * Timer set operation failed, expiration too late. + * Truncate the expiration time against the maximum timeout for the + * timer pool. */ ODP_TIMER_TOOLATE = -2, -/** - * Timer set operation failed because no event specified and no event present - * in the timer (timer inactive/expired). - */ + + /** + * Timer set operation failed because no event specified and no event + * present in the timer (timer inactive/expired). + */ ODP_TIMER_NOEVENT = -3 + } odp_timer_set_t;
/** @@ -96,8 +99,8 @@ typedef enum { * Maximum timer pool name length in chars including null char */
-/** Timer pool parameters - * Timer pool parameters are used when creating and querying timer pools. +/** + * Timer pool parameters */ typedef struct { /** Timeout resolution in nanoseconds. Timer pool must serve timeouts @@ -187,9 +190,8 @@ int odp_timer_capability(odp_timer_clk_src_t clk_src, * @return Timer pool handle on success * @retval ODP_TIMER_POOL_INVALID on failure and errno set */ -odp_timer_pool_t -odp_timer_pool_create(const char *name, - const odp_timer_pool_param_t *params); +odp_timer_pool_t odp_timer_pool_create(const char *name, + const odp_timer_pool_param_t *params);
/** * Start a timer pool @@ -207,60 +209,67 @@ void odp_timer_pool_start(void); * Destroy a timer pool, freeing all resources. * All timers must have been freed. * - * @param tpid Timer pool identifier + * @param timer_pool Timer pool */ -void odp_timer_pool_destroy(odp_timer_pool_t tpid); +void odp_timer_pool_destroy(odp_timer_pool_t timer_pool);
/** * Convert timer ticks to nanoseconds * - * @param tpid Timer pool identifier - * @param ticks Timer ticks + * @param timer_pool Timer pool + * @param ticks Timer ticks * * @return Nanoseconds */ -uint64_t odp_timer_tick_to_ns(odp_timer_pool_t tpid, uint64_t ticks); +uint64_t odp_timer_tick_to_ns(odp_timer_pool_t timer_pool, uint64_t ticks);
/** * Convert nanoseconds to timer ticks * - * @param tpid Timer pool identifier - * @param ns Nanoseconds + * @param timer_pool Timer pool + * @param ns Nanoseconds * * @return Timer ticks */ -uint64_t odp_timer_ns_to_tick(odp_timer_pool_t tpid, uint64_t ns); +uint64_t odp_timer_ns_to_tick(odp_timer_pool_t timer_pool, uint64_t ns);
/** * Current tick value * - * @param tpid Timer pool identifier + * @param timer_pool Timer pool * * @return Current time in timer ticks */ -uint64_t odp_timer_current_tick(odp_timer_pool_t tpid); +uint64_t odp_timer_current_tick(odp_timer_pool_t timer_pool);
/** * ODP timer pool information and configuration */ - typedef struct { - odp_timer_pool_param_t param; /**< Parameters specified at creation */ - uint32_t cur_timers; /**< Number of currently allocated timers */ - uint32_t hwm_timers; /**< High watermark of allocated timers */ - const char *name; /**< Name of timer pool */ + /** Parameters specified at creation */ + odp_timer_pool_param_t param; + + /** Number of currently allocated timers */ + uint32_t cur_timers; + + /** High watermark of allocated timers */ + uint32_t hwm_timers; + + /** Name of timer pool */ + const char *name; + } odp_timer_pool_info_t;
/** * Query timer pool configuration and current state * - * @param tpid Timer pool identifier - * @param[out] info Pointer to information buffer + * @param timer_pool Timer pool + * @param[out] info Pointer to information buffer * * @retval 0 on success * @retval <0 on failure. Info could not be retrieved. */ -int odp_timer_pool_info(odp_timer_pool_t tpid, +int odp_timer_pool_info(odp_timer_pool_t timer_pool, odp_timer_pool_info_t *info);
/** @@ -270,15 +279,14 @@ int odp_timer_pool_info(odp_timer_pool_t tpid, * the timer pool. The user_ptr is copied to timeouts and can be retrieved * using the odp_timeout_user_ptr() call. * - * @param tpid Timer pool identifier - * @param queue Destination queue for timeout notifications - * @param user_ptr User defined pointer or NULL to be copied to timeouts + * @param timer_pool Timer pool + * @param queue Destination queue for timeout notifications + * @param user_ptr User defined pointer or NULL to be copied to timeouts * * @return Timer handle on success * @retval ODP_TIMER_INVALID on failure and errno set. */ -odp_timer_t odp_timer_alloc(odp_timer_pool_t tpid, - odp_queue_t queue, +odp_timer_t odp_timer_alloc(odp_timer_pool_t timer_pool, odp_queue_t queue, void *user_ptr);
/** @@ -289,11 +297,12 @@ odp_timer_t odp_timer_alloc(odp_timer_pool_t tpid, * The timeout event for an expired timer will not be returned. It is the * responsibility of the application to handle this timeout when it is received. * - * @param tim Timer handle + * @param timer Timer + * * @return Event handle of timeout event * @retval ODP_EVENT_INVALID on failure */ -odp_event_t odp_timer_free(odp_timer_t tim); +odp_event_t odp_timer_free(odp_timer_t timer);
/** * Set (or reset) a timer with absolute expiration time @@ -395,6 +404,7 @@ odp_event_t odp_timeout_to_event(odp_timeout_t tmo);
/** * Check for fresh timeout + * * If the corresponding timer has been reset or cancelled since this timeout * was enqueued, the timeout is stale (not fresh). * @@ -424,6 +434,7 @@ uint64_t odp_timeout_tick(odp_timeout_t tmo);
/** * Return user pointer for the timeout + * * The user pointer was specified when the timer was allocated. * * @param tmo Timeout handle @@ -456,41 +467,41 @@ void odp_timeout_free(odp_timeout_t tmo); /** * Get printable value for an odp_timer_pool_t * - * @param hdl odp_timer_pool_t handle to be printed - * @return uint64_t value that can be used to print/display this - * handle + * @param timer_pool odp_timer_pool_t handle to be printed + * + * @return uint64_t value that can be used to print/display this handle * * @note This routine is intended to be used for diagnostic purposes * to enable applications to generate a printable value that represents * an odp_timer_pool_t handle. */ -uint64_t odp_timer_pool_to_u64(odp_timer_pool_t hdl); +uint64_t odp_timer_pool_to_u64(odp_timer_pool_t timer_pool);
/** * Get printable value for an odp_timer_t * - * @param hdl odp_timer_t handle to be printed - * @return uint64_t value that can be used to print/display this - * handle + * @param timer odp_timer_t handle to be printed + * + * @return uint64_t value that can be used to print/display this handle * * @note This routine is intended to be used for diagnostic purposes * to enable applications to generate a printable value that represents * an odp_timer_t handle. */ -uint64_t odp_timer_to_u64(odp_timer_t hdl); +uint64_t odp_timer_to_u64(odp_timer_t timer);
/** * Get printable value for an odp_timeout_t * - * @param hdl odp_timeout_t handle to be printed - * @return uint64_t value that can be used to print/display this - * handle + * @param tmo odp_timeout_t handle to be printed + * + * @return uint64_t value that can be used to print/display this handle * * @note This routine is intended to be used for diagnostic purposes * to enable applications to generate a printable value that represents * an odp_timeout_t handle. */ -uint64_t odp_timeout_to_u64(odp_timeout_t hdl); +uint64_t odp_timeout_to_u64(odp_timeout_t tmo);
/** * @}
commit 064dbc1d3b0d284ae7ab4db5e20fa0f6f2ce8c56 Author: Petri Savolainen petri.savolainen@nokia.com Date: Fri May 10 16:48:08 2019 +0300
api: timer: clarify timer set specification
Timer API intention has always been to allow any event type to be used as timeout events. Application should use ODP_EVENT_TIMEOUT type events (odp_timeout_t) by default, but also other event types may be used. Also, clarified timer set/reset functionality of odp_timer_set_abs() and _rel() functions.
API functionality not changed, just wording updated.
Signed-off-by: Petri Savolainen petri.savolainen@nokia.com Reviewed-by: Matias Elo matias.elo@nokia.com Reviewed-by: Stanislaw Kardach skardach@marvell.com
diff --git a/include/odp/api/spec/timer.h b/include/odp/api/spec/timer.h index ee314914f..1ad7ae4f6 100644 --- a/include/odp/api/spec/timer.h +++ b/include/odp/api/spec/timer.h @@ -1,4 +1,6 @@ /* Copyright (c) 2013-2018, Linaro Limited + * Copyright (c) 2019, Nokia + * * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -83,8 +85,8 @@ typedef enum { * timer pool. */ ODP_TIMER_TOOLATE = -2, /** - * Timer set operation failed because no timeout event specified and no - * timeout event present in the timer (timer inactive/expired). + * Timer set operation failed because no event specified and no event present + * in the timer (timer inactive/expired). */ ODP_TIMER_NOEVENT = -3 } odp_timer_set_t; @@ -294,73 +296,87 @@ odp_timer_t odp_timer_alloc(odp_timer_pool_t tpid, odp_event_t odp_timer_free(odp_timer_t tim);
/** - * Set a timer (absolute time) with a user-provided timeout event + * Set (or reset) a timer with absolute expiration time + * + * This function sets a timer to expire at a specific time. If the timer is + * already running (set and not yet expired), the function updates (resets) it + * with a new expiration time and optionally with a new event. A successful + * reset operation with a new event outputs the old event. A failed reset + * operation does not modify the timer. + * + * The user provided event can be of any event type, but only ODP_EVENT_TIMEOUT + * type events (odp_timeout_t) carry timeout specific metadata. Furthermore, + * timer performance may have been optimized for that event type. When the timer + * expires, the event is enqueued to the destination queue of the timer. * - * Set (arm) the timer to expire at specific time. The timeout - * event will be enqueued when the timer expires. + * @param timer Timer + * @param abs_tick Absolute expiration time in timer ticks + * @param[in,out] tmo_ev Pointer to an event handle. The event is enqueued + * when the timer expires. Use NULL when resetting the + * timer without changing the event. When resetting the + * timer with a new event, a successful operation + * outputs the old event here. * - * @param tim Timer - * @param abs_tck Expiration time in absolute timer ticks - * @param[in,out] tmo_ev Reference to an event variable that points to - * timeout event or NULL to reuse the existing timeout event. Any existing - * timeout event that is replaced by a successful set operation will be - * returned here. + * @retval ODP_TIMER_SUCCESS Success + * @retval ODP_TIMER_TOOEARLY Failure. Expiration time is too near to + * the current time. + * @retval ODP_TIMER_TOOLATE Failure. Expiration time is too far from + * the current time. + * @retval ODP_TIMER_NOEVENT Failure. Set operation: No event provided. + * Reset operation: Too late to reset the timer. * - * @retval ODP_TIMER_SUCCESS Operation succeeded - * @retval ODP_TIMER_TOOEARLY Operation failed because expiration tick too - * early - * @retval ODP_TIMER_TOOLATE Operation failed because expiration tick too - * late - * @retval ODP_TIMER_NOEVENT Operation failed because timeout event not - * specified in odp_timer_set call and not present in timer + * @see odp_timer_set_rel(), odp_timer_alloc(), odp_timer_cancel() */ -int odp_timer_set_abs(odp_timer_t tim, - uint64_t abs_tck, +int odp_timer_set_abs(odp_timer_t timer, uint64_t abs_tick, odp_event_t *tmo_ev);
/** - * Set a timer with a relative expiration time and user-provided event. + * Set (or reset) a timer with relative expiration time * - * Set (arm) the timer to expire at a relative future time. + * Like odp_timer_set_abs(), but the expiration time is relative to the current + * time: expiration tick = odp_timer_current_tick() + 'rel_tick'. * - * @param tim Timer - * @param rel_tck Expiration time in timer ticks relative to current time of - * the timer pool the timer belongs to - * @param[in,out] tmo_ev Reference to an event variable that points to - * timeout event or NULL to reuse the existing timeout event. Any existing - * timeout event that is replaced by a successful set operation will be - * returned here. + * @param timer Timer + * @param rel_tick Expiration time relative to current time of + * the timer pool in timer ticks + * @param[in,out] tmo_ev Pointer to an event handle. The event is enqueued + * when the timer expires. Use NULL when resetting the + * timer without changing the event. When resetting the + * timer with a new event, a successful operation + * outputs the old event here. * - * @retval ODP_TIMER_SUCCESS Operation succeeded - * @retval ODP_TIMER_TOOEARLY Operation failed because expiration tick too - * early - * @retval ODP_TIMER_TOOLATE Operation failed because expiration tick too - * late - * @retval ODP_TIMER_NOEVENT Operation failed because timeout event not - * specified in call and not present in timer + * @retval ODP_TIMER_SUCCESS Success + * @retval ODP_TIMER_TOOEARLY Failure. Expiration time is too near to + * the current time. + * @retval ODP_TIMER_TOOLATE Failure. Expiration time is too far from + * the current time. + * @retval ODP_TIMER_NOEVENT Failure. Set operation: No event provided. + * Reset operation: Too late to reset the timer. + * + * @see odp_timer_set_abs(), odp_timer_alloc(), odp_timer_cancel() */ -int odp_timer_set_rel(odp_timer_t tim, - uint64_t rel_tck, +int odp_timer_set_rel(odp_timer_t timer, uint64_t rel_tick, odp_event_t *tmo_ev);
/** * Cancel a timer * - * Cancel a timer, preventing future expiration and delivery. Return any - * present timeout event. + * Cancel a timer, preventing future expiration and event delivery. Return any + * present event. * * A timer that has already expired may be impossible to cancel and the timeout * will instead be delivered to the destination queue. * - * @param tim Timer - * @param[out] tmo_ev Pointer to an event variable - * @retval 0 Success, active timer cancelled, timeout returned in '*tmo_ev' - * @retval <0 on failure (timer inactive or already expired) + * @param timer Timer + * @param[out] tmo_ev Pointer to an event handle for output + * + * @retval 0 Success. Active timer cancelled, timeout returned in 'tmo_ev' + * @retval <0 Failure. Timer inactive or already expired. */ -int odp_timer_cancel(odp_timer_t tim, odp_event_t *tmo_ev); +int odp_timer_cancel(odp_timer_t timer, odp_event_t *tmo_ev);
/** - * Return timeout handle that is associated with timeout event + * Get timeout handle from a ODP_EVENT_TIMEOUT type event * * @param ev An event of type ODP_EVENT_TIMEOUT *
-----------------------------------------------------------------------
Summary of changes: configure.ac | 2 +- include/odp/api/spec/time.h | 18 +- include/odp/api/spec/timer.h | 293 ++++++++++++------- platform/linux-generic/odp_timer.c | 130 ++++++--- test/validation/api/time/time.c | 11 + test/validation/api/timer/timer.c | 570 +++++++++++++++++++++++++++++++++---- 6 files changed, 833 insertions(+), 191 deletions(-)
hooks/post-receive