At runtime, UST checks if the LTTng clock source is available
authorJulien Desfossez <julien.desfossez@polymtl.ca>
Wed, 12 Jan 2011 08:36:37 +0000 (09:36 +0100)
committerNils Carlson <nils.carlson@ericsson.com>
Thu, 13 Jan 2011 17:49:51 +0000 (18:49 +0100)
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: Julien Desfossez <julien.desfossez@polymtl.ca>
Signed-off-by: David Goulet <david.goulet@polymtl.ca>
Acked-by: Nils Carlson <nils.carlson@ericsson.com>
include/ust/clock.h
libust/tracectl.c

index cb8a663ceb229f75ab19cc69db8df4390084f8ea..ac0a2d5a9e1453460f4225f968d0496d059c3633 100644 (file)
@@ -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>
    - 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;
@@ -93,8 +67,8 @@ static __inline__ u64 trace_clock_read64(void)
                "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));
-       
+               : [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;
 }
 
@@ -116,4 +120,4 @@ static __inline__ u32 trace_clock_freq_scale(void)
        return 1;
 }
 
-#endif /* UST_CLOCK_H */
+#endif /* _UST_CLOCK_H */
index b783c76e2ba8c87f0aa7280408c7c60236c885fe..4f016bb08215ae43844adf50f1c651d50716b489 100644 (file)
@@ -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;
This page took 0.026623 seconds and 4 git commands to generate.