aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/linux-dpdk/Makefile.am2
l---------[-rw-r--r--]platform/linux-dpdk/include/odp/api/plat/time_types.h44
-rw-r--r--platform/linux-dpdk/include/odp_time_internal.h44
-rw-r--r--platform/linux-dpdk/odp_time.c339
4 files changed, 220 insertions, 209 deletions
diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am
index 1482f1bc2..c1497f0f6 100644
--- a/platform/linux-dpdk/Makefile.am
+++ b/platform/linux-dpdk/Makefile.am
@@ -155,7 +155,7 @@ noinst_HEADERS = \
${top_srcdir}/platform/linux-generic/include/odp_schedule_if.h \
${top_srcdir}/platform/linux-generic/include/odp_sorted_list_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_shm_internal.h \
- ${srcdir}/include/odp_time_internal.h \
+ ${top_srcdir}/platform/linux-generic/include/odp_time_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_timer_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_timer_wheel_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_traffic_mngr_internal.h \
diff --git a/platform/linux-dpdk/include/odp/api/plat/time_types.h b/platform/linux-dpdk/include/odp/api/plat/time_types.h
index e53ad2f97..b42bc83c2 100644..120000
--- a/platform/linux-dpdk/include/odp/api/plat/time_types.h
+++ b/platform/linux-dpdk/include/odp/api/plat/time_types.h
@@ -1,43 +1 @@
-/* Copyright (c) 2016, Linaro Limited
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/**
- * @file
- *
- * ODP time service
- */
-
-#ifndef ODP_TIME_TYPES_H_
-#define ODP_TIME_TYPES_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @addtogroup odp_time
- * @{
- **/
-
-/**
- * @internal Time structure used to isolate odp-linux implementation from
- * the linux timespec structure, which is dependent on POSIX extension level.
- */
-typedef struct odp_time_t {
- int64_t tv_sec; /**< @internal Seconds or DPDK ticks */
- int64_t tv_nsec; /**< @internal Nanoseconds */
-} odp_time_t;
-
-#define ODP_TIME_NULL ((odp_time_t){0, 0})
-
-/**
- * @}
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+../../../../../linux-generic/include/odp/api/plat/time_types.h \ No newline at end of file
diff --git a/platform/linux-dpdk/include/odp_time_internal.h b/platform/linux-dpdk/include/odp_time_internal.h
deleted file mode 100644
index 8cbf81419..000000000
--- a/platform/linux-dpdk/include/odp_time_internal.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2016, Linaro Limited
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/**
- * @file
- *
- * ODP time service
- */
-
-#ifndef ODP_TIME_INTERNAL_H_
-#define ODP_TIME_INTERNAL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef uint64_t (*time_to_ns_fn) (odp_time_t time);
-typedef odp_time_t (*time_diff_fn) (odp_time_t t2, odp_time_t t1);
-typedef odp_time_t (*time_curr_fn)(void);
-typedef int (*time_cmp_fn) (odp_time_t t2, odp_time_t t1);
-typedef odp_time_t (*time_sum_fn) (odp_time_t t1, odp_time_t t2);
-typedef odp_time_t (*time_local_from_ns_fn) (uint64_t ns);
-typedef uint64_t (*time_local_res_fn)(void);
-typedef uint64_t (*time_to_u64_fn) (odp_time_t time);
-
-typedef struct time_handler_ {
- time_to_ns_fn time_to_ns;
- time_diff_fn time_diff;
- time_curr_fn time_curr;
- time_cmp_fn time_cmp;
- time_sum_fn time_sum;
- time_local_from_ns_fn time_local_from_ns;
- time_local_res_fn time_local_res;
- time_to_u64_fn time_to_u64;
-} time_handler_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/platform/linux-dpdk/odp_time.c b/platform/linux-dpdk/odp_time.c
index 9ca3109f1..6c066a5b5 100644
--- a/platform/linux-dpdk/odp_time.c
+++ b/platform/linux-dpdk/odp_time.c
@@ -13,105 +13,182 @@
#include <odp_time_internal.h>
#include <rte_cycles.h>
#include <string.h>
+#include <inttypes.h>
+
+typedef uint64_t (*time_to_ns_fn) (odp_time_t time);
+typedef odp_time_t (*time_cur_fn)(void);
+typedef odp_time_t (*time_from_ns_fn) (uint64_t ns);
+typedef uint64_t (*time_res_fn)(void);
+
+typedef struct time_handler_ {
+ time_to_ns_fn time_to_ns;
+ time_cur_fn time_cur;
+ time_from_ns_fn time_from_ns;
+ time_res_fn time_res;
+} time_handler_t;
+
+typedef struct time_global_t {
+ struct timespec spec_start;
+ int use_hw;
+ uint64_t hw_start;
+ uint64_t hw_freq_hz;
+ /* DPDK specific */
+ time_handler_t handler;
+ double tick_per_nsec;
+ double nsec_per_tick;
+} time_global_t;
+
+static time_global_t global;
+
+/*
+ * Posix timespec based functions
+ */
+
+static inline uint64_t time_spec_diff_nsec(struct timespec *t2,
+ struct timespec *t1)
+{
+ struct timespec diff;
+ uint64_t nsec;
-typedef union {
- odp_time_t ex;
- struct timespec in;
-} _odp_time_t;
+ diff.tv_sec = t2->tv_sec - t1->tv_sec;
+ diff.tv_nsec = t2->tv_nsec - t1->tv_nsec;
-static odp_time_t start_time;
-static time_handler_t time_handler;
-double tick_per_nsec;
-double nsec_per_tick;
+ if (diff.tv_nsec < 0) {
+ diff.tv_nsec += ODP_TIME_SEC_IN_NS;
+ diff.tv_sec -= 1;
+ }
+
+ nsec = (diff.tv_sec * ODP_TIME_SEC_IN_NS) + diff.tv_nsec;
+
+ return nsec;
+}
-static inline uint64_t time_local_res_dpdk(void)
+static inline odp_time_t time_spec_cur(void)
{
- return rte_get_timer_hz();
+ int ret;
+ odp_time_t time;
+ struct timespec sys_time;
+
+ ret = clock_gettime(CLOCK_MONOTONIC_RAW, &sys_time);
+ if (odp_unlikely(ret != 0))
+ ODP_ABORT("clock_gettime failed\n");
+
+ time.nsec = time_spec_diff_nsec(&sys_time, &global.spec_start);
+
+ return time;
}
-static inline
-uint64_t time_to_ns(odp_time_t time)
+static inline uint64_t time_spec_res(void)
{
- uint64_t ns;
+ int ret;
+ struct timespec tres;
- ns = time.tv_sec * ODP_TIME_SEC_IN_NS;
- ns += time.tv_nsec;
+ ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres);
+ if (odp_unlikely(ret != 0))
+ ODP_ABORT("clock_getres failed\n");
- return ns;
+ return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec;
}
-static inline uint64_t time_to_ns_dpdk(odp_time_t time)
+static inline uint64_t time_spec_to_ns(odp_time_t time)
{
- return (time.tv_sec * nsec_per_tick);
+ return time.nsec;
}
-static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1)
+static inline odp_time_t time_spec_from_ns(uint64_t ns)
{
odp_time_t time;
- time.tv_sec = t2.tv_sec - t1.tv_sec;
- time.tv_nsec = t2.tv_nsec - t1.tv_nsec;
-
- if (time.tv_nsec < 0) {
- time.tv_nsec += ODP_TIME_SEC_IN_NS;
- --time.tv_sec;
- }
+ time.nsec = ns;
return time;
}
-static inline odp_time_t time_diff_dpdk(odp_time_t t2, odp_time_t t1)
+/*
+ * HW time counter based functions
+ */
+
+static inline odp_time_t time_hw_cur(void)
{
odp_time_t time;
- time.tv_sec = t2.tv_sec - t1.tv_sec;
+ time.count = cpu_global_time() - global.hw_start;
+
return time;
}
-static inline odp_time_t time_curr(void)
+static inline uint64_t time_hw_res(void)
{
- int ret;
- _odp_time_t time;
+ /* Promise a bit lower resolution than average cycle counter
+ * frequency */
+ return global.hw_freq_hz / 10;
+}
- ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
- if (odp_unlikely(ret != 0))
- ODP_ABORT("clock_gettime failed\n");
- return time.ex;
+static inline uint64_t time_hw_to_ns(odp_time_t time)
+{
+ uint64_t nsec;
+ uint64_t freq_hz = global.hw_freq_hz;
+ uint64_t count = time.count;
+ uint64_t sec = 0;
+
+ if (count >= freq_hz) {
+ sec = count / freq_hz;
+ count = count - sec * freq_hz;
+ }
+
+ nsec = (ODP_TIME_SEC_IN_NS * count) / freq_hz;
+
+ return (sec * ODP_TIME_SEC_IN_NS) + nsec;
}
-static inline odp_time_t time_curr_dpdk(void)
+static inline odp_time_t time_hw_from_ns(uint64_t ns)
{
odp_time_t time;
+ uint64_t count;
+ uint64_t freq_hz = global.hw_freq_hz;
+ uint64_t sec = 0;
+
+ if (ns >= ODP_TIME_SEC_IN_NS) {
+ sec = ns / ODP_TIME_SEC_IN_NS;
+ ns = ns - sec * ODP_TIME_SEC_IN_NS;
+ }
+
+ count = sec * freq_hz;
+ count += (ns * freq_hz) / ODP_TIME_SEC_IN_NS;
+
+ time.count = count;
- time.tv_sec = rte_get_timer_cycles();
return time;
}
-static inline odp_time_t time_local(void)
+/*
+ * Common functions
+ */
+
+static inline odp_time_t time_cur(void)
{
- odp_time_t time;
+ if (global.use_hw)
+ return time_hw_cur();
- time = time_handler.time_curr();
- return time_handler.time_diff(time, start_time);
+ return time_spec_cur();
}
-static inline int time_cmp(odp_time_t t2, odp_time_t t1)
+static inline uint64_t time_res(void)
{
- if (t2.tv_sec < t1.tv_sec)
- return -1;
+ if (global.use_hw)
+ return time_hw_res();
- if (t2.tv_sec > t1.tv_sec)
- return 1;
-
- return t2.tv_nsec - t1.tv_nsec;
+ return time_spec_res();
}
-static inline int time_cmp_dpdk(odp_time_t t2, odp_time_t t1)
+static inline int time_cmp(odp_time_t t2, odp_time_t t1)
{
- if (t2.tv_sec < t1.tv_sec)
- return -1;
- if (t2.tv_sec > t1.tv_sec)
+ if (odp_likely(t2.u64 > t1.u64))
return 1;
+
+ if (t2.u64 < t1.u64)
+ return -1;
+
return 0;
}
@@ -119,61 +196,67 @@ static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2)
{
odp_time_t time;
- time.tv_sec = t2.tv_sec + t1.tv_sec;
- time.tv_nsec = t2.tv_nsec + t1.tv_nsec;
-
- if (time.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) {
- time.tv_nsec -= ODP_TIME_SEC_IN_NS;
- ++time.tv_sec;
- }
+ time.u64 = t1.u64 + t2.u64;
return time;
}
-static inline odp_time_t time_sum_dpdk(odp_time_t t1, odp_time_t t2)
+static inline uint64_t time_to_ns(odp_time_t time)
{
- odp_time_t time;
+ if (global.use_hw)
+ return time_hw_to_ns(time);
- time.tv_sec = t2.tv_sec + t1.tv_sec;
- return time;
+ return time_spec_to_ns(time);
+}
+
+static inline odp_time_t time_from_ns(uint64_t ns)
+{
+ if (global.use_hw)
+ return time_hw_from_ns(ns);
+
+ return time_spec_from_ns(ns);
}
-static inline odp_time_t time_local_from_ns(uint64_t ns)
+static inline uint64_t time_res_dpdk(void)
+{
+ return rte_get_timer_hz();
+}
+
+static inline uint64_t time_to_ns_dpdk(odp_time_t time)
+{
+ return (time.u64 * global.nsec_per_tick);
+}
+
+static inline odp_time_t time_cur_dpdk(void)
{
odp_time_t time;
- time.tv_sec = ns / ODP_TIME_SEC_IN_NS;
- time.tv_nsec = ns - time.tv_sec * ODP_TIME_SEC_IN_NS;
+ time.u64 = rte_get_timer_cycles() - global.hw_start;
return time;
}
-static inline odp_time_t time_local_from_ns_dpdk(uint64_t ns)
+static inline odp_time_t time_from_ns_dpdk(uint64_t ns)
{
odp_time_t time;
- time.tv_sec = ns * tick_per_nsec;
+
+ time.u64 = ns * global.tick_per_nsec;
+
return time;
}
+static inline odp_time_t time_local(void)
+{
+ return global.handler.time_cur();
+}
+
static inline void time_wait_until(odp_time_t time)
{
odp_time_t cur;
do {
cur = time_local();
- } while (time_handler.time_cmp(time, cur) > 0);
-}
-
-static inline uint64_t time_local_res(void)
-{
- int ret;
- struct timespec tres;
-
- ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres);
- if (odp_unlikely(ret != 0))
- ODP_ABORT("clock_getres failed\n");
-
- return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec;
+ } while (time_cmp(time, cur) > 0);
}
odp_time_t odp_time_local(void)
@@ -188,49 +271,53 @@ odp_time_t odp_time_global(void)
odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1)
{
- return time_handler.time_diff(t2, t1);
+ odp_time_t time;
+
+ time.u64 = t2.u64 - t1.u64;
+
+ return time;
}
uint64_t odp_time_to_ns(odp_time_t time)
{
- return time_handler.time_to_ns(time);
+ return global.handler.time_to_ns(time);
}
odp_time_t odp_time_local_from_ns(uint64_t ns)
{
- return time_handler.time_local_from_ns(ns);
+ return global.handler.time_from_ns(ns);
}
odp_time_t odp_time_global_from_ns(uint64_t ns)
{
- return time_handler.time_local_from_ns(ns);
+ return global.handler.time_from_ns(ns);
}
int odp_time_cmp(odp_time_t t2, odp_time_t t1)
{
- return time_handler.time_cmp(t2, t1);
+ return time_cmp(t2, t1);
}
odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
{
- return time_handler.time_sum(t1, t2);
+ return time_sum(t1, t2);
}
uint64_t odp_time_local_res(void)
{
- return time_handler.time_local_res();
+ return global.handler.time_res();
}
uint64_t odp_time_global_res(void)
{
- return time_handler.time_local_res();
+ return global.handler.time_res();
}
void odp_time_wait_ns(uint64_t ns)
{
odp_time_t cur = time_local();
- odp_time_t wait = time_handler.time_local_from_ns(ns);
- odp_time_t end_time = time_handler.time_sum(cur, wait);
+ odp_time_t wait = global.handler.time_from_ns(ns);
+ odp_time_t end_time = time_sum(cur, wait);
time_wait_until(end_time);
}
@@ -240,11 +327,6 @@ void odp_time_wait_until(odp_time_t time)
return time_wait_until(time);
}
-static uint64_t time_to_u64_dpdk(odp_time_t time)
-{
- return time.tv_sec;
-}
-
static odp_bool_t is_invariant_tsc_supported(void)
{
FILE *file;
@@ -291,37 +373,52 @@ static inline odp_bool_t is_dpdk_timer_cycles_support(void)
int odp_time_init_global(void)
{
+ int ret = 0;
+
+ memset(&global, 0, sizeof(time_global_t));
+
if (is_dpdk_timer_cycles_support()) {
- time_handler.time_to_ns = time_to_ns_dpdk;
- time_handler.time_diff = time_diff_dpdk;
- time_handler.time_curr = time_curr_dpdk;
- time_handler.time_cmp = time_cmp_dpdk;
- time_handler.time_sum = time_sum_dpdk;
- time_handler.time_local_from_ns = time_local_from_ns_dpdk;
- time_handler.time_local_res = time_local_res_dpdk;
- time_handler.time_to_u64 = time_to_u64_dpdk;
- tick_per_nsec = (double)time_local_res_dpdk() /
+ global.handler.time_to_ns = time_to_ns_dpdk;
+ global.handler.time_cur = time_cur_dpdk;
+ global.handler.time_from_ns = time_from_ns_dpdk;
+ global.handler.time_res = time_res_dpdk;
+ global.tick_per_nsec = (double)time_res_dpdk() /
(double)ODP_TIME_SEC_IN_NS;
- nsec_per_tick = (double)ODP_TIME_SEC_IN_NS /
- (double)time_local_res_dpdk();
- } else {
- time_handler.time_to_ns = time_to_ns;
- time_handler.time_diff = time_diff;
- time_handler.time_curr = time_curr;
- time_handler.time_cmp = time_cmp;
- time_handler.time_sum = time_sum;
- time_handler.time_local_from_ns = time_local_from_ns;
- time_handler.time_local_res = time_local_res;
- time_handler.time_to_u64 = time_to_u64;
+ global.nsec_per_tick = (double)ODP_TIME_SEC_IN_NS /
+ (double)time_res_dpdk();
+
+ global.hw_start = rte_get_timer_cycles();
+ if (global.hw_start == 0)
+ return -1;
+ else
+ return 0;
}
- start_time = time_handler.time_curr();
- if (time_handler.time_cmp(start_time, ODP_TIME_NULL) == 0) {
- ODP_ABORT("initiate odp time failed\n");
- return -1;
- } else {
+ global.handler.time_to_ns = time_to_ns;
+ global.handler.time_cur = time_cur;
+ global.handler.time_from_ns = time_from_ns;
+ global.handler.time_res = time_res;
+
+ if (cpu_has_global_time()) {
+ global.use_hw = 1;
+ global.hw_freq_hz = cpu_global_time_freq();
+
+ if (global.hw_freq_hz == 0)
+ return -1;
+
+ printf("HW time counter freq: %" PRIu64 " hz\n\n",
+ global.hw_freq_hz);
+
+ global.hw_start = cpu_global_time();
return 0;
}
+
+ global.spec_start.tv_sec = 0;
+ global.spec_start.tv_nsec = 0;
+
+ ret = clock_gettime(CLOCK_MONOTONIC_RAW, &global.spec_start);
+
+ return ret;
}
int odp_time_term_global(void)