[v2,1/6] eal: add internal API for current time

Message ID 20210214021616.26970-2-dmitry.kozliuk@gmail.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series net/pcap: build on Windows |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Dmitry Kozlyuk Feb. 14, 2021, 2:16 a.m. UTC
  Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
to obtain current time with microsecond precision on all platforms.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 lib/librte_eal/include/rte_time.h    | 17 +++++++++++++++++
 lib/librte_eal/rte_eal_exports.def   |  1 +
 lib/librte_eal/unix/eal_unix_timer.c | 13 +++++++++++++
 lib/librte_eal/version.map           |  1 +
 lib/librte_eal/windows/eal_timer.c   | 21 ++++++++++++++++++++-
 5 files changed, 52 insertions(+), 1 deletion(-)
  

Comments

Nick Connolly March 1, 2021, 10:39 p.m. UTC | #1
> Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
> to obtain current time with microsecond precision on all platforms.
>
Acked-by: Nick Connolly <nick.connolly@mayadata.io>
  
Jie Zhou March 5, 2021, 5:50 p.m. UTC | #2
On Sun, Feb 14, 2021 at 05:16:11AM +0300, Dmitry Kozlyuk wrote:
> Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
> to obtain current time with microsecond precision on all platforms.
> 
> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> ---
>  lib/librte_eal/include/rte_time.h    | 17 +++++++++++++++++
>  lib/librte_eal/rte_eal_exports.def   |  1 +
>  lib/librte_eal/unix/eal_unix_timer.c | 13 +++++++++++++
>  lib/librte_eal/version.map           |  1 +
>  lib/librte_eal/windows/eal_timer.c   | 21 ++++++++++++++++++++-
>  5 files changed, 52 insertions(+), 1 deletion(-)
>
Acked-by: Jie Zhou <jizh@linux.microsoft.com>
  
Thomas Monjalon March 16, 2021, 9:18 a.m. UTC | #3
14/02/2021 03:16, Dmitry Kozlyuk:
> Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
> to obtain current time with microsecond precision on all platforms.

Please could you replace the current use of gettimeofday?
  
Stephen Hemminger March 16, 2021, 6:59 p.m. UTC | #4
On Sun, 14 Feb 2021 05:16:11 +0300
Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:

> +rte_time_get_us(struct rte_time_us *now)
> +{
> +	struct timeval sys;
> +
> +	gettimeofday(&sys, NULL);
> +	now->sec = sys.tv_sec;
> +	now->usec = sys.tv_usec;
> +}

Why would drivers want the default (wall clock) time instead
of using monotonic clock. The wall clock gets changed by NTP
and that is rarely what you want except for the case of log messages.
  
Dmitry Kozlyuk March 16, 2021, 8:07 p.m. UTC | #5
2021-03-16 11:59 (UTC-0700), Stephen Hemminger:
> On Sun, 14 Feb 2021 05:16:11 +0300
> Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:
> 
> > +rte_time_get_us(struct rte_time_us *now)
> > +{
> > +	struct timeval sys;
> > +
> > +	gettimeofday(&sys, NULL);
> > +	now->sec = sys.tv_sec;
> > +	now->usec = sys.tv_usec;
> > +}  
> 
> Why would drivers want the default (wall clock) time instead
> of using monotonic clock. The wall clock gets changed by NTP
> and that is rarely what you want except for the case of log messages.

* gettimeofday() is mostly used to measure time (tests, hns3 PMD), so you're
right, monotonic clock is what that code really needs.

* ena PMD uses gettimeofday() with pthread_cond_timedwait() without calling
pthread_cond_setclock(), which is a bug, I believe.

* hns3 PMD actually uses gettimeofday() for logs.

For wall clock time there is C11 timespec_get(), so I agree this API should
be changed to monotonic, thanks.
  
Morten Brørup March 17, 2021, 9:50 a.m. UTC | #6
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Dmitry Kozlyuk
> Sent: Tuesday, March 16, 2021 9:08 PM
> 
> 2021-03-16 11:59 (UTC-0700), Stephen Hemminger:
> > On Sun, 14 Feb 2021 05:16:11 +0300
> > Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:
> >
> > > +rte_time_get_us(struct rte_time_us *now)
> > > +{
> > > +	struct timeval sys;
> > > +
> > > +	gettimeofday(&sys, NULL);
> > > +	now->sec = sys.tv_sec;
> > > +	now->usec = sys.tv_usec;
> > > +}
> >
> > Why would drivers want the default (wall clock) time instead
> > of using monotonic clock. The wall clock gets changed by NTP
> > and that is rarely what you want except for the case of log messages.
> 
> * gettimeofday() is mostly used to measure time (tests, hns3 PMD), so
> you're
> right, monotonic clock is what that code really needs.

If using monotonic time here, we don't need a struct. A single 64 bit integer counting microseconds can hold thousands of years.

> 
> * ena PMD uses gettimeofday() with pthread_cond_timedwait() without
> calling
> pthread_cond_setclock(), which is a bug, I believe.
> 
> * hns3 PMD actually uses gettimeofday() for logs.
> 
> For wall clock time there is C11 timespec_get(), so I agree this API
> should
> be changed to monotonic, thanks.
  

Patch

diff --git a/lib/librte_eal/include/rte_time.h b/lib/librte_eal/include/rte_time.h
index 5ad7c8841..50fa4f889 100644
--- a/lib/librte_eal/include/rte_time.h
+++ b/lib/librte_eal/include/rte_time.h
@@ -8,6 +8,8 @@ 
 #include <stdint.h>
 #include <time.h>
 
+#include <rte_compat.h>
+
 #define NSEC_PER_SEC             1000000000L
 
 /**
@@ -98,4 +100,19 @@  rte_ns_to_timespec(uint64_t nsec)
 	return ts;
 }
 
+/* Point of time with microsecond precision. */
+struct rte_time_us {
+	int64_t sec;  /**< Number of whole seconds. */
+	int64_t usec; /**< Fractional part of second in [0, 999999]. */
+};
+
+/**
+ * Get current system time.
+ *
+ * @param now
+ *  Receives current system time.
+ */
+__rte_internal
+void rte_time_get_us(struct rte_time_us *now);
+
 #endif /* _RTE_TIME_H_ */
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index 474cf123f..cb691f7bc 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -334,3 +334,4 @@  EXPORTS
 	rte_mem_map
 	rte_mem_page_size
 	rte_mem_unmap
+	rte_time_get_us
diff --git a/lib/librte_eal/unix/eal_unix_timer.c b/lib/librte_eal/unix/eal_unix_timer.c
index cc5015910..5612fdebe 100644
--- a/lib/librte_eal/unix/eal_unix_timer.c
+++ b/lib/librte_eal/unix/eal_unix_timer.c
@@ -4,7 +4,10 @@ 
 
 #include <time.h>
 
+#include <sys/time.h>
+
 #include <rte_cycles.h>
+#include <rte_time.h>
 
 void
 rte_delay_us_sleep(unsigned int us)
@@ -27,3 +30,13 @@  rte_delay_us_sleep(unsigned int us)
 		ind = 1 - ind;
 	}
 }
+
+void
+rte_time_get_us(struct rte_time_us *now)
+{
+	struct timeval sys;
+
+	gettimeofday(&sys, NULL);
+	now->sec = sys.tv_sec;
+	now->usec = sys.tv_usec;
+}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index fce90a112..405bed766 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,4 +421,5 @@  INTERNAL {
 	rte_mem_map;
 	rte_mem_page_size;
 	rte_mem_unmap;
+	rte_time_get_us;
 };
diff --git a/lib/librte_eal/windows/eal_timer.c b/lib/librte_eal/windows/eal_timer.c
index b070cb775..a5c42106a 100644
--- a/lib/librte_eal/windows/eal_timer.c
+++ b/lib/librte_eal/windows/eal_timer.c
@@ -9,6 +9,7 @@ 
 #include <rte_cycles.h>
 #include <rte_eal.h>
 #include <rte_errno.h>
+#include <rte_time.h>
 #include "eal_private.h"
 
 #define US_PER_SEC 1E6
@@ -85,10 +86,28 @@  get_tsc_freq(void)
 	return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_10MHZ);
 }
 
-
 int
 rte_eal_timer_init(void)
 {
 	set_tsc_freq();
 	return 0;
 }
+
+void
+rte_time_get_us(struct rte_time_us *now)
+{
+	/* 100ns ticks from 1601-01-01 to 1970-01-01 */
+	static const uint64_t EPOCH = 116444736000000000ULL;
+	static const uint64_t TICKS_PER_USEC = 10;
+	static const uint64_t USEC_PER_SEC = 1000000;
+
+	FILETIME ft;
+	uint64_t ticks, sec;
+
+	GetSystemTimePreciseAsFileTime(&ft);
+	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+	ticks -= EPOCH;
+	sec = ticks / (TICKS_PER_USEC * USEC_PER_SEC);
+	now->sec = sec;
+	now->usec = ticks / TICKS_PER_USEC - sec * USEC_PER_SEC;
+}