[ltt-dev] Kernel crashes when creating a trace
Mathieu Desnoyers
compudj at krystal.dyndns.org
Wed Nov 18 17:18:58 EST 2009
* Mathieu Desnoyers (mathieu.desnoyers at polymtl.ca) wrote:
> * Ashwin Tanugula (ashwin.tanugula at broadcom.com) wrote:
> >
> >
> > > >
> > > > Without "return 1;", it still hangs, I will enable lockdep and send you the log ASAP.
> > > >
> >
> > > Oh ! I found the mistake. Erroneous "cmpxchg" in the 32-bit version of
> > > the trace clock. That should work without the return 1; now. Please try 0.174.
> >
> > I am using patch-2.6.31.6-lttng-0.176, ltt-control-0.77-18112009 and lttv-0.12.23-18112009.
> >
> > And I still see the hang without "return 1:"
>
> OK. Can you please try with this patch applied on top of 0.176 ? This
> should be very close to mips64 which, AFAIK, should work and does not
> need this workaround to deal with 64-bit values. Sorry it's taking so
> long. It would help if I could get my hands on a MIPS32 board. More
> comments after the patch.
[snip snip]
I compared the mips code to the approach I took for intel (they were
quite similar) and found the discrepancy. Please ignore the previous
patch I just sent, and try this one instead:
mips32 fix trace clock spinlock (v2)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
---
arch/mips/kernel/trace-clock.c | 71 ++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 35 deletions(-)
Index: linux-2.6-lttng/arch/mips/kernel/trace-clock.c
===================================================================
--- linux-2.6-lttng.orig/arch/mips/kernel/trace-clock.c 2009-11-18 16:47:48.000000000 -0500
+++ linux-2.6-lttng/arch/mips/kernel/trace-clock.c 2009-11-18 17:16:59.000000000 -0500
@@ -18,37 +18,11 @@ static DEFINE_SPINLOCK(async_tsc_lock);
static int async_tsc_refcount; /* Number of readers */
static int async_tsc_enabled; /* Async TSC enabled on all online CPUs */
-/*
- * Support for architectures with non-sync TSCs.
- * When the local TSC is discovered to lag behind the highest TSC counter, we
- * increment the TSC count of an amount that should be, ideally, lower than the
- * execution time of this routine, in cycles : this is the granularity we look
- * for : we must be able to order the events.
- */
-
-#if BITS_PER_LONG == 64
-notrace u64 trace_clock_async_tsc_read(void)
+#if (BITS_PER_LONG == 64)
+static inline u64 trace_clock_cmpxchg64(u64 *ptr, u64 old, u64 new)
{
- u64 new_tsc, last_tsc;
-
- WARN_ON(!async_tsc_refcount || !async_tsc_enabled);
- new_tsc = trace_clock_read_synthetic_tsc();
- do {
- last_tsc = trace_clock_last_tsc;
- if (new_tsc < last_tsc)
- new_tsc = last_tsc + TRACE_CLOCK_MIN_PROBE_DURATION;
- /*
- * If cmpxchg fails with a value higher than the new_tsc, don't
- * retry : the value has been incremented and the events
- * happened almost at the same time.
- * We must retry if cmpxchg fails with a lower value :
- * it means that we are the CPU with highest frequency and
- * therefore MUST update the value.
- */
- } while (cmpxchg64(&trace_clock_last_tsc, last_tsc, new_tsc) < new_tsc);
- return new_tsc;
+ return cmpxchg64(ptr, old, new);
}
-EXPORT_SYMBOL_GPL(trace_clock_async_tsc_read);
#else
/*
* Emulate an atomic 64-bits update with a spinlock.
@@ -59,6 +33,9 @@ EXPORT_SYMBOL_GPL(trace_clock_async_tsc_
static raw_spinlock_t trace_clock_lock =
(raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+/*
+ * Must be called under irqoff+spinlock on MIPS32.
+ */
static inline u64 trace_clock_cmpxchg64(u64 *ptr, u64 old, u64 new)
{
u64 val;
@@ -68,18 +45,41 @@ static inline u64 trace_clock_cmpxchg64(
*ptr = new;
return val;
}
+#endif
+
+/*
+ * Must be called under irqoff+spinlock on MIPS32.
+ */
+static cycles_t read_last_tsc(void)
+{
+ return trace_clock_last_tsc;
+}
+
+/*
+ * Support for architectures with non-sync TSCs.
+ * When the local TSC is discovered to lag behind the highest TSC counter, we
+ * increment the TSC count of an amount that should be, ideally, lower than the
+ * execution time of this routine, in cycles : this is the granularity we look
+ * for : we must be able to order the events.
+ *
+ * MIPS32 does not have atomic 64-bit updates. Emulate it with irqoff+spinlock.
+ */
notrace u64 trace_clock_async_tsc_read(void)
{
u64 new_tsc, last_tsc;
+#if (BITS_PER_LONG == 32)
unsigned long flags;
- WARN_ON(!async_tsc_refcount || !async_tsc_enabled);
local_irq_save(flags);
__raw_spin_lock(&trace_clock_lock);
+#endif
+
+ WARN_ON(!async_tsc_refcount || !async_tsc_enabled);
new_tsc = trace_clock_read_synthetic_tsc();
+ barrier();
+ last_tsc = read_last_tsc();
do {
- last_tsc = trace_clock_last_tsc;
if (new_tsc < last_tsc)
new_tsc = last_tsc + TRACE_CLOCK_MIN_PROBE_DURATION;
/*
@@ -90,15 +90,16 @@ notrace u64 trace_clock_async_tsc_read(v
* it means that we are the CPU with highest frequency and
* therefore MUST update the value.
*/
- } while (trace_clock_cmpxchg64(&trace_clock_last_tsc, last_tsc,
- new_tsc) < new_tsc);
+ last_tsc = trace_clock_cmpxchg64(&trace_clock_last_tsc,
+ last_tsc, new_tsc);
+ } while (unlikely(last_tsc < new_tsc));
+#if (BITS_PER_LONG == 32)
__raw_spin_unlock(&trace_clock_lock);
local_irq_restore(flags);
+#endif
return new_tsc;
}
EXPORT_SYMBOL_GPL(trace_clock_async_tsc_read);
-#endif
-
static void update_timer_ipi(void *info)
{
--
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
More information about the lttng-dev
mailing list