[ltt-dev] trace_clock_update() spinning

Mike McTernan mmcternan at airvana.com
Fri Feb 5 04:37:12 EST 2010


* Mathieu Desnoyers wrote:
> You could possibly get a better resolution by creating a trace clock
> specific for your architecture.

So I took this advice.  The Freescale i.MX51 has a Cortex A8 processor,
so has the same ARM performance counters available as the OMAP3.  In
fact I think these counters exist on all ARMs from ARM11 onwards - I'm
not sure if later LTT patches provide generic ARM support, but that
would be nice (except the platform specifics such as the broken bit 31
on OMAP!).  

Anyway, the results are brilliant.  Using LTTng I've quickly found some
areas of poor performance in our own drivers (excessive interrupts &
busy waiting), and also some scheduler mal-configuration with SCHED_FIFO
threads.  Thanks for this great tool!

A patch of my changes follows.  I'm not proposing it for inclusion in
LTTng, just optimistically publishing it in case others using i.MX51
could benefit.  It's based on the 2.6.28.2 kernel (Freescale's ER9 BSP)
patched with the 0.88 LTTng patch set.

Kind Regards,

Mike

diff --exclude=.svn -Naur
linux-2.6.28.mx51-er9.clean/arch/arm/plat-mxc/Makefile
linux-2.6.28.mx51-er9/arch/arm/plat-mxc/Makefile
--- linux-2.6.28.mx51-er9.clean/arch/arm/plat-mxc/Makefile
2010-02-04 19:19:29.980122357 +0000
+++ linux-2.6.28.mx51-er9/arch/arm/plat-mxc/Makefile	2010-02-02
21:45:13.028732364 +0000
@@ -56,3 +56,6 @@
 obj-y += serialxc.o
 endif
 endif
+
+# LTTng trace clock
+obj-$(CONFIG_HAVE_TRACE_CLOCK) += trace-clock.o
diff --exclude=.svn -Naur
linux-2.6.28.mx51-er9.clean/arch/arm/plat-mxc/trace-clock.c
linux-2.6.28.mx51-er9/arch/arm/plat-mxc/trace-clock.c
--- linux-2.6.28.mx51-er9.clean/arch/arm/plat-mxc/trace-clock.c
1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.mx51-er9/arch/arm/plat-mxc/trace-clock.c
2010-02-04 19:14:26.302127386 +0000
@@ -0,0 +1,90 @@
+/*
+ * kernel/arch/arm/plat-mxc/trace-clock.c
+ *
+ * (C) Copyright	2010 -
+ * 		Michael McTernan (Michael.McTernan at airvana.com)
+ *
+ * Tracing clock for i.MX51.
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/trace-clock.h>
+#include <mach/hardware.h>
+
+static int trace_clock_refcount;
+static DEFINE_MUTEX(trace_clock_mutex);
+
+unsigned long trace_clk_rate;
+
+static void enable_trace_clock(void)
+{
+  unsigned int r1;
+
+  /* Start perf counters */
+  r1 = 0;
+  asm("mrc p15, 0, %0, c9, c12, 0" : "=r" (r1));
+  r1 |= 0x1; /* enable counters */
+  asm("mcr p15, 0, %0, c9, c12, 0" : : "r" (r1));
+
+   /* Enable cycle counter */
+   r1 = 0x80000000;
+   asm("mcr p15, 0, %0, c9, c12, 1" : : "r" (r1));
+}
+
+static void disable_trace_clock(void)
+{
+  /* Disable cycle counter */
+  unsigned int r1 = 0x80000000;
+  asm("mcr p15, 0, %0, c9, c12, 2" : : "r" (r1));
+}
+
+void get_trace_clock(void)
+{
+	get_synthetic_tsc();
+	mutex_lock(&trace_clock_mutex);
+	if (trace_clock_refcount++)
+		goto end;
+	enable_trace_clock();
+end:
+	mutex_unlock(&trace_clock_mutex);
+}
+EXPORT_SYMBOL_GPL(get_trace_clock);
+
+void put_trace_clock(void)
+{
+	mutex_lock(&trace_clock_mutex);
+	WARN_ON(trace_clock_refcount <= 0);
+	if (trace_clock_refcount != 1)
+		goto end;
+	disable_trace_clock();
+end:
+	trace_clock_refcount--;
+	mutex_unlock(&trace_clock_mutex);
+	put_synthetic_tsc();
+}
+EXPORT_SYMBOL_GPL(put_trace_clock);
+
+
+static int __init init_trace_clock(void)
+{
+  struct clk *cpu_clk;
+
+  /* Get the CPU clock */
+  cpu_clk = clk_get(NULL, "cpu_clk");
+  if(IS_ERR(cpu_clk)) {
+    return -ENOMEM;
+  }
+
+  trace_clk_rate = clk_get_rate(cpu_clk);
+
+  clk_put(cpu_clk);
+
+  return 0;
+}
+
+early_initcall(init_trace_clock);
+
diff --exclude=.svn -Naur
linux-2.6.28.mx51-er9.clean/include/asm-arm/trace-clock.h
linux-2.6.28.mx51-er9/include/asm-arm/trace-clock.h
--- linux-2.6.28.mx51-er9.clean/include/asm-arm/trace-clock.h
1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.mx51-er9/include/asm-arm/trace-clock.h	2010-02-03
13:07:15.324714176 +0000
@@ -0,0 +1,65 @@
+#ifndef _ASM_ARM_TRACE_CLOCK_H
+#define _ASM_ARM_TRACE_CLOCK_H
+
+/*
+ * include/asm-generic/trace-clock.h
+ *
+ * Copyright (C) 2010 - Michael McTernan (mmcternan at airvana.com)
+ *
+ * Tracing clock for i.MX51.
+ */
+
+#include <asm/atomic.h>
+
+extern unsigned long trace_clk_rate;
+
+static inline u32 trace_clock_read32(void)
+{
+  u32 val;
+
+  __asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
+
+  return val;
+}
+
+#ifdef CONFIG_HAVE_TRACE_CLOCK_32_TO_64
+extern u64 trace_clock_read_synthetic_tsc(void);
+extern void get_synthetic_tsc(void);
+extern void put_synthetic_tsc(void);
+
+static inline u64 trace_clock_read64(void)
+{
+	return trace_clock_read_synthetic_tsc();
+}
+#else
+static inline void get_synthetic_tsc(void)
+{
+}
+
+static inline void put_synthetic_tsc(void)
+{
+}
+
+static inline u64 trace_clock_read64(void)
+{
+	return trace_clock_read32();
+}
+#endif
+
+static inline unsigned int trace_clock_frequency(void)
+{
+	return trace_clk_rate;
+}
+
+static inline u32 trace_clock_freq_scale(void)
+{
+	return 1;
+}
+
+extern void get_trace_clock(void);
+extern void put_trace_clock(void);
+
+static inline void set_trace_clock_is_sync(int state)
+{
+}
+#endif /* _ASM_ARM_TRACE_CLOCK_H */
diff --exclude=.svn -Naur linux-2.6.28.mx51-er9.clean/init/Kconfig
linux-2.6.28.mx51-er9/init/Kconfig
--- linux-2.6.28.mx51-er9.clean/init/Kconfig	2010-02-05
08:01:53.582861126 +0000
+++ linux-2.6.28.mx51-er9/init/Kconfig	2010-02-02 21:43:08.340585489
+0000
@@ -344,7 +344,7 @@
 # Architectures with a specialized tracing clock should select this.
 #
 config HAVE_TRACE_CLOCK
-	def_bool n
+	def_bool y
 
 config HAVE_TRACE_CLOCK_GENERIC
 	bool
@@ -356,7 +356,7 @@
 # Architectures with only a 32-bits clock source should select this.
 #
 config HAVE_TRACE_CLOCK_32_TO_64
-	def_bool n
+	def_bool y
 
 #
 # Architectures which need to dynamically detect if their TSC is
unsynchronized


--
Mike




More information about the lttng-dev mailing list