[ltt-dev] trace_clock_update() spinning

Mathieu Desnoyers mathieu.desnoyers at efficios.com
Fri Feb 5 10:16:13 EST 2010


* Mike McTernan (mmcternan at airvana.com) wrote:
> * 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.

Hi Mike,

Thanks for the patch!

A few questions:

- Does your architecture support power management sleep modes ? If yes, does the
  cycle counter stop in sleep modes ?
- Does your architecture support dynamic ferquency scaling ?
- Would you agree for me to integrate it in the lttng project and transfer
  non-exclusive relicensing rights to the LTTng maintainer ? Basically, the idea
  is to release it under dual GPLv2/LGPLv2.1 licenses, but I start to think that
  it might be just easier to use the gdb approach for LTTng contributions, where
  the project maintainers have the freedom to decide license changes. This way
  we would not have to ask permission from everyone if we need to do a license
  change for the LTTng project overall.

Thanks,

Mathieu

> 
> 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