[ltt-dev] [UST PATCH] Add LTTng clock source support

David Goulet david.goulet at polymtl.ca
Tue Jan 11 11:12:25 EST 2011


From: Julien Desfossez <julien.desfossez at polymtl.ca>

At runtime, UST checks if the LTTng clock source is available
If not, CLOCK_MONOTONIC is the default fallback.

This makes UST use the LTTng kernel clock source. With this
clock support, LTTng and UST traces are perfectly synchronize.
Traces from these two tracer can be merged for analysis.

LTTng 0.240 or higher is needed for this new clock source.

Signed-off-by: David Goulet <david.goulet at polymtl.ca>
---
 include/ust/clock.h |  106 ++++++++++++++++++++++++++------------------------
 libust/tracectl.c   |   10 +++++
 2 files changed, 65 insertions(+), 51 deletions(-)

diff --git a/include/ust/clock.h b/include/ust/clock.h
index cb8a663..df56550 100644
--- a/include/ust/clock.h
+++ b/include/ust/clock.h
@@ -15,8 +15,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
-#ifndef UST_CLOCK_H
-#define UST_CLOCK_H
+#ifndef _UST_CLOCK_H
+#define _UST_CLOCK_H
 
 #include <time.h>
 #include <sys/time.h>
@@ -29,56 +29,30 @@
    - gettimeofday() clock
 
    Microbenchmarks on Linux 2.6.30 on Core2 Duo 3GHz (functions are inlined):
-     Calls (100000000) to tsc(): 4004035641 cycles or 40 cycles/call
-     Calls (100000000) to gettimeofday(): 9723158352 cycles or 97 cycles/call
+	 Calls (100000000) to tsc(): 4004035641 cycles or 40 cycles/call
+	 Calls (100000000) to gettimeofday(): 9723158352 cycles or 97 cycles/call
 
    For merging traces with the kernel, a time source compatible with that of
    the kernel is necessary.
 
    Instead of gettimeofday(), we are now using clock_gettime for better
    precision and monotonicity.
-
 */
 
-#define TRACE_CLOCK_GENERIC
-#ifdef TRACE_CLOCK_GENERIC
-
-static __inline__ u64 trace_clock_read64(void)
-{
+#if __i386__ || __x86_64__
+/* Only available for x86 arch */
+#define CLOCK_TRACE_FREQ  14
+#define CLOCK_TRACE  15
+union lttng_timespec {
 	struct timespec ts;
-	u64 retval;
-
-	clock_gettime(CLOCK_MONOTONIC, &ts);
-	retval = ts.tv_sec;
-	retval *= 1000000000;
-	retval += ts.tv_nsec;
-
-	return retval;
-}
-
-#else
-
-#if __i386 || __x86_64
-
-/* WARNING: Make sure to set frequency and scaling functions that will not
- * result in lttv timestamps (sec.nsec) with seconds greater than 2**32-1.
- */
-static __inline__ u64 trace_clock_read64(void)
-{
-	uint32_t low;
-	uint32_t high;
-	uint64_t retval;
-	__asm__ volatile ("rdtsc\n" : "=a" (low), "=d" (high));
-
-	retval = high;
-	retval <<= 32;
-	return retval | low;
-}
-
-#endif /* __i386 || __x86_64 */
+	u64 lttng_ts;
+};
+#endif /* __i386__ || __x86_64__ */
 
-#ifdef __PPC__
+static int ust_clock_source;
 
+/* Choosing correct trace clock */
+#if __PPC__
 static __inline__ u64 trace_clock_read64(void)
 {
 	unsigned long tb_l;
@@ -87,14 +61,14 @@ static __inline__ u64 trace_clock_read64(void)
 	u64 tb;
 
 	__asm__ (
-		"1:\n\t"
-		"mftbu %[rhigh]\n\t"
-		"mftb %[rlow]\n\t"
-		"mftbu %[rhigh2]\n\t"
-		"cmpw %[rhigh],%[rhigh2]\n\t"
-		"bne 1b\n\t"
-	: [rhigh] "=r" (tb_h), [rhigh2] "=r" (tb_h2), [rlow] "=r" (tb_l));
-	
+			"1:\n\t"
+			"mftbu %[rhigh]\n\t"
+			"mftb %[rlow]\n\t"
+			"mftbu %[rhigh2]\n\t"
+			"cmpw %[rhigh],%[rhigh2]\n\t"
+			"bne 1b\n\t"
+			: [rhigh] "=r" (tb_h), [rhigh2] "=r" (tb_h2), [rlow] "=r" (tb_l));
+
 	tb = tb_h;
 	tb <<= 32;
 	tb |= tb_l;
@@ -102,12 +76,42 @@ static __inline__ u64 trace_clock_read64(void)
 	return tb;
 }
 
-#endif /* __PPC__ */
+#else	/* !__PPC__ */
 
-#endif /* ! UST_TRACE_CLOCK_GENERIC */
+static __inline__ u64 trace_clock_read64(void)
+{
+	struct timespec ts;
+	u64 retval;
+	union lttng_timespec *lts = (union lttng_timespec *) &ts;
+
+	clock_gettime(ust_clock_source, &ts);
+	/*
+	 * Clock source can change when loading the binary (tracectl.c)
+	 * so we must check if the clock source has changed before
+	 * returning the correct value
+	 */
+	if (likely(ust_clock_source == CLOCK_TRACE)) {
+		retval = lts->lttng_ts;
+	} else { /* CLOCK_MONOTONIC */
+		retval = ts.tv_sec;
+		retval *= 1000000000;
+		retval += ts.tv_nsec;
+	}
+
+	return retval;
+}
+
+#endif /* __PPC__ */
 
 static __inline__ u64 trace_clock_frequency(void)
 {
+	struct timespec ts;
+	union lttng_timespec *lts = (union lttng_timespec *) &ts;
+
+	if (likely(ust_clock_source == CLOCK_TRACE)) {
+		clock_gettime(CLOCK_TRACE_FREQ, &ts);
+		return lts->lttng_ts;
+	}
 	return 1000000000LL;
 }
 
diff --git a/libust/tracectl.c b/libust/tracectl.c
index b783c76..4f016bb 100644
--- a/libust/tracectl.c
+++ b/libust/tracectl.c
@@ -39,6 +39,7 @@
 #include <ust/marker.h>
 #include <ust/tracepoint.h>
 #include <ust/tracectl.h>
+#include <ust/clock.h>
 #include "tracer.h"
 #include "usterr.h"
 #include "ustcomm.h"
@@ -1262,6 +1263,15 @@ static void __attribute__((constructor)) init()
 
 	create_listener();
 
+	/* Get clock the clock source type */
+	struct timespec ts;
+	/* Default clock source */
+	ust_clock_source = CLOCK_TRACE;
+	if (clock_gettime(ust_clock_source, &ts) != 0) {
+		ust_clock_source = CLOCK_MONOTONIC;
+		DBG("UST traces will not be synchronized with LTTng traces");
+	}
+
 	autoprobe_val = getenv("UST_AUTOPROBE");
 	if (autoprobe_val) {
 		struct marker_iter iter;
-- 
1.7.3.5





More information about the lttng-dev mailing list