[PATCH 23/25] lib/cobalt: dovetail: allow representing time as count of nanoseconds

Jan Kiszka jan.kiszka at siemens.com
Thu May 20 23:44:33 CEST 2021


From: Philippe Gerum <rpm at xenomai.org>

When the core runs on top of Dovetail, all time values are represented
as counts of nanoseconds, in which case a Cobalt tick equals a
nanosecond.

Introduce inline wrappers for tick-to/from-ns conversion which are
nops in the latter case. Cobalt passes us a null clock frequency at
binding time (__cobalt_tsc_clockfreq) when conversion is not needed;
otherwise, the frequency is used in scaled maths for converting
timestamps between their hardware tick and nanosec representation.

Signed-off-by: Philippe Gerum <rpm at xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
---
 include/cobalt/ticks.h | 50 +++++++++++++++++++++++++++++++++++++++---
 lib/cobalt/ticks.c     | 42 +++++++++++++++++++----------------
 2 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/include/cobalt/ticks.h b/include/cobalt/ticks.h
index 2d0132db78..e59d86d499 100644
--- a/include/cobalt/ticks.h
+++ b/include/cobalt/ticks.h
@@ -18,17 +18,61 @@
 #ifndef _COBALT_TICKS_H
 #define _COBALT_TICKS_H
 
+#include <stdbool.h>
 #include <cobalt/uapi/kernel/types.h>
 
+/*
+ * Depending on the underlying pipeline support, we may represent time
+ * stamps as count of nanoseconds (Dovetail), or as values of the
+ * hardware tick counter (aka TSC) available with the platform
+ * (I-pipe). In the latter - legacy - case, we need to convert from
+ * TSC values to nanoseconds and conversely via scaled maths. This
+ * indirection will go away once support for the I-pipe is removed.
+ */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-xnsticks_t cobalt_ticks_to_ns(xnsticks_t ticks);
+extern unsigned long long __cobalt_tsc_clockfreq;
+
+static inline bool cobalt_use_legacy_tsc(void)
+{
+	return !!__cobalt_tsc_clockfreq;
+}
+
+xnsticks_t __cobalt_tsc_to_ns(xnsticks_t ticks);
+
+xnsticks_t __cobalt_tsc_to_ns_rounded(xnsticks_t ticks);
+
+xnsticks_t __cobalt_ns_to_tsc(xnsticks_t ns);
 
-xnsticks_t cobalt_ticks_to_ns_rounded(xnsticks_t ticks);
+static inline
+xnsticks_t cobalt_ns_to_ticks(xnsticks_t ns)
+{
+	if (cobalt_use_legacy_tsc())
+		return __cobalt_ns_to_tsc(ns);
 
-xnsticks_t cobalt_ns_to_ticks(xnsticks_t ns);
+	return ns;
+}
+
+static inline
+xnsticks_t cobalt_ticks_to_ns(xnsticks_t ticks)
+{
+	if (cobalt_use_legacy_tsc())
+		return __cobalt_tsc_to_ns(ticks);
+
+	return ticks;
+}
+
+static inline
+xnsticks_t cobalt_ticks_to_ns_rounded(xnsticks_t ticks)
+{
+	if (cobalt_use_legacy_tsc())
+		return __cobalt_tsc_to_ns_rounded(ticks);
+
+	return ticks;
+}
 
 unsigned long long cobalt_divrem_billion(unsigned long long value,
 					 unsigned long *rem);
diff --git a/lib/cobalt/ticks.c b/lib/cobalt/ticks.c
index 89d7f51e38..8313258117 100644
--- a/lib/cobalt/ticks.c
+++ b/lib/cobalt/ticks.c
@@ -20,7 +20,7 @@
 #include <asm/xenomai/tsc.h>
 #include "internal.h"
 
-static unsigned long long clockfreq;
+unsigned long long __cobalt_tsc_clockfreq;
 
 #ifdef XNARCH_HAVE_LLMULSHFT
 
@@ -31,11 +31,6 @@ static unsigned int tsc_scale, tsc_shift;
 static struct xnarch_u32frac tsc_frac;
 static struct xnarch_u32frac bln_frac;
 
-xnsticks_t cobalt_ns_to_ticks(xnsticks_t ns)
-{
-	return xnarch_nodiv_llimd(ns, tsc_frac.frac, tsc_frac.integ);
-}
-
 unsigned long long cobalt_divrem_billion(unsigned long long value,
 					 unsigned long *rem)
 {
@@ -52,21 +47,26 @@ unsigned long long cobalt_divrem_billion(unsigned long long value,
 	return q;
 }
 
+xnsticks_t __cobalt_ns_to_tsc(xnsticks_t ns)
+{
+	return xnarch_nodiv_llimd(ns, tsc_frac.frac, tsc_frac.integ);
+}
+
 #else /* !XNARCH_HAVE_NODIV_LLIMD */
 
-xnsticks_t cobalt_ns_to_ticks(xnsticks_t ns)
+xnsticks_t __cobalt_ns_to_tsc(xnsticks_t ns)
 {
 	return xnarch_llimd(ns, 1 << tsc_shift, tsc_scale);
 }
 
 #endif /* !XNARCH_HAVE_NODIV_LLIMD */
 
-xnsticks_t cobalt_ticks_to_ns(xnsticks_t ticks)
+xnsticks_t __cobalt_tsc_to_ns(xnsticks_t ticks)
 {
 	return xnarch_llmulshft(ticks, tsc_scale, tsc_shift);
 }
 
-xnsticks_t cobalt_ticks_to_ns_rounded(xnsticks_t ticks)
+xnsticks_t __cobalt_tsc_to_ns_rounded(xnsticks_t ticks)
 {
 	unsigned int shift = tsc_shift - 1;
 	return (xnarch_llmulshft(ticks, tsc_scale, shift) + 1) / 2;
@@ -74,19 +74,19 @@ xnsticks_t cobalt_ticks_to_ns_rounded(xnsticks_t ticks)
 
 #else  /* !XNARCH_HAVE_LLMULSHFT */
 
-xnsticks_t cobalt_ticks_to_ns(xnsticks_t ticks)
+xnsticks_t __cobalt_tsc_to_ns(xnsticks_t ticks)
 {
-	return xnarch_llimd(ticks, 1000000000, clockfreq);
+	return xnarch_llimd(ticks, 1000000000, __cobalt_tsc_clockfreq);
 }
 
-xnsticks_t cobalt_ticks_to_ns_rounded(xnsticks_t ticks)
+xnsticks_t __cobalt_tsc_to_ns_rounded(xnsticks_t ticks)
 {
-	return (xnarch_llimd(ticks, 1000000000, clockfreq/2) + 1) / 2;
+	return (xnarch_llimd(ticks, 1000000000, __cobalt_tsc_clockfreq/2) + 1) / 2;
 }
 
-xnsticks_t cobalt_ns_to_ticks(xnsticks_t ns)
+xnsticks_t __cobalt_ns_to_tsc(xnsticks_t ns)
 {
-	return xnarch_llimd(ns, clockfreq, 1000000000);
+	return xnarch_llimd(ns, __cobalt_tsc_clockfreq, 1000000000);
 }
 #endif /* !XNARCH_HAVE_LLMULSHFT */
 
@@ -101,12 +101,16 @@ unsigned long long cobalt_divrem_billion(unsigned long long value,
 
 void cobalt_ticks_init(unsigned long long freq)
 {
-	clockfreq = freq;
+	__cobalt_tsc_clockfreq = freq;
 #ifdef XNARCH_HAVE_LLMULSHFT
-	xnarch_init_llmulshft(1000000000, freq, &tsc_scale, &tsc_shift);
+	if (freq) {
+		xnarch_init_llmulshft(1000000000, freq, &tsc_scale, &tsc_shift);
 #ifdef XNARCH_HAVE_NODIV_LLIMD
-	xnarch_init_u32frac(&tsc_frac, 1 << tsc_shift, tsc_scale);
-	xnarch_init_u32frac(&bln_frac, 1, 1000000000);
+		xnarch_init_u32frac(&tsc_frac, 1 << tsc_shift, tsc_scale);
+#endif
+	}
 #endif
+#ifdef XNARCH_HAVE_NODIV_LLIMD
+	xnarch_init_u32frac(&bln_frac, 1, 1000000000);
 #endif
 }
-- 
2.26.2




More information about the Xenomai mailing list