Commit 1eeef00e authored by Philippe Gerum's avatar Philippe Gerum Committed by Jan Kiszka

lib/cobalt: dovetail: allow representing time as count of nanoseconds

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's avatarPhilippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 540d637e
......@@ -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);
......
......@@ -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
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment