[2/2] Optimize odp time api leveraging dpdk.

Message ID CAOdUko2q5gf3a_g0QzVDDZ7a0U6bc6CkRUriOpNfqGek8aXSQg@mail.gmail.com
State New
Headers show

Commit Message

Wenxian Li April 25, 2016, 4:28 p.m.
Correct the subject.

Optimize odp time api leveraging dpdk.
The priority of timer source is:
TSC (if invariant TSC is supported) > HPET (If enabled) > syscall
clockgettime

Signed-off-by: wenxian li <wenxian.li@linaro.org>

---
 platform/linux-dpdk/include/odp/plat/time_types.h |  42 ++++-
 platform/linux-dpdk/include/odp_time_internal.h   |  44 +++++
 platform/linux-dpdk/odp_init.c                    |  12 +-
 platform/linux-dpdk/odp_time.c                    | 186
+++++++++++++++++++---
 4 files changed, 253 insertions(+), 31 deletions(-)
 mode change 120000 => 100644
platform/linux-dpdk/include/odp/plat/time_types.h
 create mode 100644 platform/linux-dpdk/include/odp_time_internal.h

 static inline int time_cmp(odp_time_t t2, odp_time_t t1)
@@ -67,6 +106,15 @@ static inline int time_cmp(odp_time_t t2, odp_time_t t1)
        return t2.tv_nsec - t1.tv_nsec;
 }

+static inline int time_cmp_dpdk(odp_time_t t2, odp_time_t t1)
+{
+       if (t2.ticks < t1.ticks)
+               return -1;
+       if (t2.ticks > t1.ticks)
+               return 1;
+       return 0;
+}
+
 static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2)
 {
        odp_time_t time;
@@ -82,6 +130,14 @@ static inline odp_time_t time_sum(odp_time_t t1,
odp_time_t t2)
        return time;
 }

+static inline odp_time_t time_sum_dpdk(odp_time_t t1, odp_time_t t2)
+{
+       odp_time_t time;
+
+       time.ticks = t2.ticks + t1.ticks;
+       return time;
+}
+
 static inline odp_time_t time_local_from_ns(uint64_t ns)
 {
        odp_time_t time;
@@ -92,13 +148,21 @@ static inline odp_time_t time_local_from_ns(uint64_t
ns)
        return time;
 }

+static inline odp_time_t time_local_from_ns_dpdk(uint64_t ns)
+{
+       odp_time_t time;
+
+       time.ticks = ns * time_local_res_dpdk() / ODP_TIME_SEC_IN_NS;
+       return time;
+}
+
 static inline void time_wait_until(odp_time_t time)
 {
        odp_time_t cur;

        do {
                cur = time_local();
-       } while (time_cmp(time, cur) > 0);
+       } while (time_handler.time_cmp(time, cur) > 0);
 }

 static inline uint64_t time_local_res(void)
@@ -125,49 +189,49 @@ odp_time_t odp_time_global(void)

 odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1)
 {
-       return time_diff(t2, t1);
+       return time_handler.time_diff(t2, t1);
 }

 uint64_t odp_time_to_ns(odp_time_t time)
 {
-       return time_to_ns(time);
+       return time_handler.time_to_ns(time);
 }

 odp_time_t odp_time_local_from_ns(uint64_t ns)
 {
-       return time_local_from_ns(ns);
+       return time_handler.time_local_from_ns(ns);
 }

 odp_time_t odp_time_global_from_ns(uint64_t ns)
 {
-       return time_local_from_ns(ns);
+       return time_handler.time_local_from_ns(ns);
 }

 int odp_time_cmp(odp_time_t t2, odp_time_t t1)
 {
-       return time_cmp(t2, t1);
+       return time_handler.time_cmp(t2, t1);
 }

 odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
 {
-       return time_sum(t1, t2);
+       return time_handler.time_sum(t1, t2);
 }

 uint64_t odp_time_local_res(void)
 {
-       return time_local_res();
+       return time_handler.time_local_res();
 }

 uint64_t odp_time_global_res(void)
 {
-       return time_local_res();
+       return time_handler.time_local_res();
 }

 void odp_time_wait_ns(uint64_t ns)
 {
        odp_time_t cur = time_local();
-       odp_time_t wait = time_local_from_ns(ns);
-       odp_time_t end_time = time_sum(cur, wait);
+       odp_time_t wait = time_handler.time_local_from_ns(ns);
+       odp_time_t end_time = time_handler.time_sum(cur, wait);

        time_wait_until(end_time);
 }
@@ -177,7 +241,7 @@ void odp_time_wait_until(odp_time_t time)
        return time_wait_until(time);
 }

-uint64_t odp_time_to_u64(odp_time_t time)
+static uint64_t time_to_u64(odp_time_t time)
 {
        int ret;
        struct timespec tres;
@@ -189,18 +253,92 @@ uint64_t odp_time_to_u64(odp_time_t time)

        resolution = (uint64_t)tres.tv_nsec;

-       return time_to_ns(time) / resolution;
+       return time_handler.time_to_ns(time) / resolution;
 }

-int odp_time_init_global(void)
+static uint64_t time_to_u64_dpdk(odp_time_t time)
 {
-       int ret;
-       _odp_time_t time;
+       return time.ticks;
+}

-       ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
-       start_time = ret ? ODP_TIME_NULL : time.ex;
+uint64_t odp_time_to_u64(odp_time_t time)
+{
+       return time_handler.time_to_u64(time);
+}
+
+static odp_bool_t is_invariant_tsc_supported(void)
+{
+       FILE  *file;
+       char  *line = NULL;
+       size_t len = 0;
+       odp_bool_t nonstop_tsc  = false;
+       odp_bool_t constant_tsc = false;
+       odp_bool_t ret = false;
+
+       file = fopen("/proc/cpuinfo", "rt");
+       while (getline(&line, &len, file) != -1) {
+               if (strstr(line, "flags") != NULL) {
+                       if (strstr(line, "constant_tsc") != NULL)
+                               constant_tsc = true;
+                       if (strstr(line, "nonstop_tsc") != NULL)
+                               nonstop_tsc = true;
+
+                       if (constant_tsc && nonstop_tsc)
+                               ret = true;
+                       else
+                               ret = false;
+
+                       free(line);
+                       fclose(file);
+                       return ret;
+               }
+       }
+       free(line);
+       fclose(file);
+       return false;
+}
+
+static inline odp_bool_t is_dpdk_timer_cycles_support(void)
+{
+       if (is_invariant_tsc_supported() == true)
+               return true;
+
+       #ifdef RTE_LIBEAL_USE_HPET
+       if (rte_eal_hpet_init(1) == 0)
+               return true;
+       #endif
+       return false;
+}
+
+int odp_time_init_global(void)
+{
+       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;
+       } 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;
+       }

-       return ret;
+       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 {
+               return 0;
+       }
 }

 int odp_time_term_global(void)
--
1.8.1.4

Comments

Zoltan Kiss May 3, 2016, 3:27 p.m. | #1
Hi,

Please move the copy of this file and the removal of the original 
symbolic link to the first patch.

On 25/04/16 17:28, Wenxian Li wrote:
>   platform/linux-dpdk/include/odp/plat/time_types.h |  42 ++++-

Patch hide | download patch | download mbox

diff --git a/platform/linux-dpdk/include/odp/plat/time_types.h
b/platform/linux-dpdk/include/odp/plat/time_types.h
deleted file mode 120000
index 31d16ad..0000000
--- a/platform/linux-dpdk/include/odp/plat/time_types.h
+++ /dev/null
@@ -1 +0,0 @@ 
-../../../../linux-generic/include/odp/plat/time_types.h
\ No newline at end of file
diff --git a/platform/linux-dpdk/include/odp/plat/time_types.h
b/platform/linux-dpdk/include/odp/plat/time_types.h
new file mode 100644
index 0000000..f7a9089
--- /dev/null
+++ b/platform/linux-dpdk/include/odp/plat/time_types.h
@@ -0,0 +1,41 @@ 
+/* 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
+
+/**
+ * @internal Time structure used to isolate linux-dpdk implementation from
+ * the linux timespec structure, which is dependent on POSIX extension
level.
+ */
+typedef union {
+       struct {
+               uint64_t ticks;  /**< @internal ticks */
+               uint64_t pad;
+       };
+       struct {
+               int64_t tv_sec;      /**< @internal Seconds */
+               int64_t tv_nsec;     /**< @internal Nanoseconds */
+       };
+} odp_time_t;
+
+#define ODP_TIME_NULL ((odp_time_t){ {0} })
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-dpdk/include/odp_time_internal.h
b/platform/linux-dpdk/include/odp_time_internal.h
new file mode 100644
index 0000000..8cbf814
--- /dev/null
+++ b/platform/linux-dpdk/include/odp_time_internal.h
@@ -0,0 +1,44 @@ 
+/* 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_init.c b/platform/linux-dpdk/odp_init.c
index 833621d..1d01aea 100644
--- a/platform/linux-dpdk/odp_init.c
+++ b/platform/linux-dpdk/odp_init.c
@@ -246,12 +246,6 @@  int odp_init_global(const odp_init_t *params,
                        odp_global_data.abort_fn = params->abort_fn;
        }

-       if (odp_time_init_global()) {
-               ODP_ERR("ODP time init failed.\n");
-               goto init_failed;
-       }
-       stage = TIME_INIT;
-
        if (odp_system_info_init()) {
                ODP_ERR("ODP system_info init failed.\n");
                goto init_failed;
@@ -263,6 +257,12 @@  int odp_init_global(const odp_init_t *params,
                return -1;
        }

+       if (odp_time_init_global()) {
+               ODP_ERR("ODP time init failed.\n");
+               goto init_failed;
+       }
+       stage = TIME_INIT;
+
        if (odp_shm_init_global()) {
                ODP_ERR("ODP shm init failed.\n");
                goto init_failed;
diff --git a/platform/linux-dpdk/odp_time.c b/platform/linux-dpdk/odp_time.c
index ca8a955..e53e502 100644
--- a/platform/linux-dpdk/odp_time.c
+++ b/platform/linux-dpdk/odp_time.c
@@ -10,6 +10,9 @@ 
 #include <odp/time.h>
 #include <odp/hints.h>
 #include <odp_debug_internal.h>
+#include <odp_time_internal.h>
+#include <rte_cycles.h>
+#include <string.h>

 typedef union {
        odp_time_t      ex;
@@ -17,9 +20,14 @@  typedef union {
 } _odp_time_t;

 static odp_time_t start_time;
+static time_handler_t time_handler;

-static inline
-uint64_t time_to_ns(odp_time_t time)
+static inline uint64_t time_local_res_dpdk(void)
+{
+       return rte_get_timer_hz();
+}
+
+static inline uint64_t time_to_ns(odp_time_t time)
 {
        uint64_t ns;

@@ -29,6 +37,11 @@  uint64_t time_to_ns(odp_time_t time)
        return ns;
 }

+static inline uint64_t time_to_ns_dpdk(odp_time_t time)
+{
+       return (time.ticks * ODP_TIME_SEC_IN_NS / time_local_res_dpdk());
+}
+
 static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1)
 {
        odp_time_t time;
@@ -44,16 +57,42 @@  static inline odp_time_t time_diff(odp_time_t t2,
odp_time_t t1)
        return time;
 }

-static inline odp_time_t time_local(void)
+static inline odp_time_t time_diff_dpdk(odp_time_t t2, odp_time_t t1)
+{
+       odp_time_t time;
+
+       time.ticks = t2.ticks - t1.ticks;
+       return time;
+}
+
+static inline odp_time_t time_curr(void)
 {
        int ret;
        _odp_time_t time;

        ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
-       if (odp_unlikely(ret != 0))
+       if (odp_unlikely(ret != 0)) {
                ODP_ABORT("clock_gettime failed\n");
+               time.ex.tv_sec = 0;
+               time.ex.tv_nsec = 0;
+       }
+       return time.ex;
+}

-       return time_diff(time.ex, start_time);
+static inline odp_time_t time_curr_dpdk(void)
+{
+       odp_time_t time;
+
+       time.ticks = rte_get_timer_cycles();
+       return time;
+}
+
+static inline odp_time_t time_local(void)
+{
+       odp_time_t time;
+
+       time = time_handler.time_curr();
+       return time_handler.time_diff(time, start_time);
 }