[v2,2/2] Optimize odp_time_local/odp_time_global related api leveraging DPDK api to avoid system call overhead.

Message ID 1462717515-97494-3-git-send-email-wofanli@gmail.com
State New
Headers show

Commit Message

Wenxian Li May 8, 2016, 2:25 p.m.
From: wenxian li <wenxian.li@linaro.org>

Signed-off-by: wenxian li <wenxian.li@linaro.org>
---
 platform/linux-dpdk/include/odp_time_internal.h |  44 ++++++
 platform/linux-dpdk/odp_init.c                  |  12 +-
 platform/linux-dpdk/odp_time.c                  | 186 +++++++++++++++++++++---
 3 files changed, 212 insertions(+), 30 deletions(-)
 create mode 100644 platform/linux-dpdk/include/odp_time_internal.h

Comments

Zoltan Kiss May 25, 2016, 5:21 p.m. | #1
On 08/05/16 15:25, wenxian li wrote:
> From: wenxian li <wenxian.li@linaro.org>
>
> Signed-off-by: wenxian li <wenxian.li@linaro.org>
> ---
>   platform/linux-dpdk/include/odp_time_internal.h |  44 ++++++
>   platform/linux-dpdk/odp_init.c                  |  12 +-
>   platform/linux-dpdk/odp_time.c                  | 186 +++++++++++++++++++++---
>   3 files changed, 212 insertions(+), 30 deletions(-)
>   create mode 100644 platform/linux-dpdk/include/odp_time_internal.h
>

(...)

> 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)

Fixing this unrelated linebreak just makes the patch less readable. I've 
removed it.

>   {
>   	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;

As Petri suggested there is no reason to put any code after abort, as it 
terminates the whole program, I've removed this too

> +	}
> +	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);
>   }
>
>   static inline int time_cmp(odp_time_t t2, odp_time_t t1)

(...)

> +static inline odp_bool_t is_dpdk_timer_cycles_support(void)
> +{
> +	if (is_invariant_tsc_supported() == true)
> +		return true;
> +
> +	#ifdef RTE_LIBEAL_USE_HPET

ifdef's start at the first column of the line.
> +	if (rte_eal_hpet_init(1) == 0)
> +		return true;
> +	#endif
> +	return false;
>   }
>
>   int odp_time_init_global(void)
>   {
> -	int ret;
> -	_odp_time_t time;
> +	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;
> +	}
>
> -	ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
> -	start_time = ret ? ODP_TIME_NULL : time.ex;
> -
> -	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)
>

Patch hide | download patch | download mbox

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);
 }
 
 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;
+}
+
+static uint64_t time_to_u64_dpdk(odp_time_t time)
+{
+	return time.ticks;
+}
+
+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)
 {
-	int ret;
-	_odp_time_t time;
+	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;
+	}
 
-	ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
-	start_time = ret ? ODP_TIME_NULL : time.ex;
-
-	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)