Patches contributed by Eötvös Lorand University


commit 0075fa80305f3231a2d5df97b00d7f55a48ea27e
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon May 12 21:20:47 2008 +0200

    ftrace: extend sysprof plugin
    
    add per CPU hrtimers.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index 6c139bc1be7e..ba55b871b3d9 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -5,19 +5,76 @@
  * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
  *
  */
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/debugfs.h>
 #include <linux/kallsyms.h>
+#include <linux/debugfs.h>
+#include <linux/hrtimer.h>
 #include <linux/uaccess.h>
-#include <linux/marker.h>
 #include <linux/ftrace.h>
+#include <linux/module.h>
+#include <linux/fs.h>
 
 #include "trace.h"
 
 static struct trace_array	*ctx_trace;
 static int __read_mostly	tracer_enabled;
 
+static const unsigned long sample_period = 1000000;
+
+/*
+ * Per CPU hrtimers that do the profiling:
+ */
+static DEFINE_PER_CPU(struct hrtimer, stack_trace_hrtimer);
+
+static enum hrtimer_restart stack_trace_timer_fn(struct hrtimer *hrtimer)
+{
+	/* trace here */
+	panic_timeout++;
+
+	hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
+
+	return HRTIMER_RESTART;
+}
+
+static void start_stack_timer(int cpu)
+{
+	struct hrtimer *hrtimer = &per_cpu(stack_trace_hrtimer, cpu);
+
+	hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	hrtimer->function = stack_trace_timer_fn;
+	hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+
+	hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL);
+}
+
+static void start_stack_timers(void)
+{
+	cpumask_t saved_mask = current->cpus_allowed;
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+		start_stack_timer(cpu);
+		printk("started timer on cpu%d\n", cpu);
+	}
+	set_cpus_allowed_ptr(current, &saved_mask);
+}
+
+static void stop_stack_timer(int cpu)
+{
+	struct hrtimer *hrtimer = &per_cpu(stack_trace_hrtimer, cpu);
+
+	hrtimer_cancel(hrtimer);
+	printk("cancelled timer on cpu%d\n", cpu);
+}
+
+static void stop_stack_timers(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		stop_stack_timer(cpu);
+}
+
 static notrace void stack_reset(struct trace_array *tr)
 {
 	int cpu;
@@ -31,11 +88,13 @@ static notrace void stack_reset(struct trace_array *tr)
 static notrace void start_stack_trace(struct trace_array *tr)
 {
 	stack_reset(tr);
+	start_stack_timers();
 	tracer_enabled = 1;
 }
 
 static notrace void stop_stack_trace(struct trace_array *tr)
 {
+	stop_stack_timers();
 	tracer_enabled = 0;
 }
 

commit f06c38103ea9dbca27c3f4d77f444ddefb5477cd
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon May 12 21:20:47 2008 +0200

    ftrace: add sysprof plugin
    
    very first baby version.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 5c2295b29f2c..e101c9a85f0f 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -75,6 +75,14 @@ config PREEMPT_TRACER
 	  enabled. This option and the irqs-off timing option can be
 	  used together or separately.)
 
+config SYSPROF_TRACER
+	bool "Sysprof Tracer"
+	depends on DEBUG_KERNEL
+	select TRACING
+	help
+	  This tracer provides the trace needed by the 'Sysprof' userspace
+	  tool.
+
 config SCHED_TRACER
 	bool "Scheduling Latency Tracer"
 	depends on HAVE_FTRACE
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index d9efbbfa2bdf..7aec123ec1d8 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_FTRACE) += libftrace.o
 
 obj-$(CONFIG_TRACING) += trace.o
 obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
+obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
 obj-$(CONFIG_FTRACE) += trace_functions.o
 obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
 obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
new file mode 100644
index 000000000000..6c139bc1be7e
--- /dev/null
+++ b/kernel/trace/trace_sysprof.c
@@ -0,0 +1,80 @@
+/*
+ * trace stack traces
+ *
+ * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
+ * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/kallsyms.h>
+#include <linux/uaccess.h>
+#include <linux/marker.h>
+#include <linux/ftrace.h>
+
+#include "trace.h"
+
+static struct trace_array	*ctx_trace;
+static int __read_mostly	tracer_enabled;
+
+static notrace void stack_reset(struct trace_array *tr)
+{
+	int cpu;
+
+	tr->time_start = ftrace_now(tr->cpu);
+
+	for_each_online_cpu(cpu)
+		tracing_reset(tr->data[cpu]);
+}
+
+static notrace void start_stack_trace(struct trace_array *tr)
+{
+	stack_reset(tr);
+	tracer_enabled = 1;
+}
+
+static notrace void stop_stack_trace(struct trace_array *tr)
+{
+	tracer_enabled = 0;
+}
+
+static notrace void stack_trace_init(struct trace_array *tr)
+{
+	ctx_trace = tr;
+
+	if (tr->ctrl)
+		start_stack_trace(tr);
+}
+
+static notrace void stack_trace_reset(struct trace_array *tr)
+{
+	if (tr->ctrl)
+		stop_stack_trace(tr);
+}
+
+static void stack_trace_ctrl_update(struct trace_array *tr)
+{
+	/* When starting a new trace, reset the buffers */
+	if (tr->ctrl)
+		start_stack_trace(tr);
+	else
+		stop_stack_trace(tr);
+}
+
+static struct tracer stack_trace __read_mostly =
+{
+	.name		= "sysprof",
+	.init		= stack_trace_init,
+	.reset		= stack_trace_reset,
+	.ctrl_update	= stack_trace_ctrl_update,
+#ifdef CONFIG_FTRACE_SELFTEST
+	.selftest    = trace_selftest_startup_stack,
+#endif
+};
+
+__init static int init_stack_trace(void)
+{
+	return register_tracer(&stack_trace);
+}
+device_initcall(init_stack_trace);

commit 489f139614596cbc956a06f5e4bb41288e276fe3
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon Feb 25 13:38:05 2008 +0100

    ftrace: fix build bug
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 911d5d80b49f..922e23d0196f 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -106,16 +106,16 @@ static inline void tracer_disable(void)
 #endif
 
 #ifdef CONFIG_IRQSOFF_TRACER
-  extern void notrace time_hardirqs_on(unsigned long a0, unsigned long a1);
-  extern void notrace time_hardirqs_off(unsigned long a0, unsigned long a1);
+  extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
+  extern void time_hardirqs_off(unsigned long a0, unsigned long a1);
 #else
 # define time_hardirqs_on(a0, a1)		do { } while (0)
 # define time_hardirqs_off(a0, a1)		do { } while (0)
 #endif
 
 #ifdef CONFIG_PREEMPT_TRACER
-  extern void notrace trace_preempt_on(unsigned long a0, unsigned long a1);
-  extern void notrace trace_preempt_off(unsigned long a0, unsigned long a1);
+  extern void trace_preempt_on(unsigned long a0, unsigned long a1);
+  extern void trace_preempt_off(unsigned long a0, unsigned long a1);
 #else
 # define trace_preempt_on(a0, a1)		do { } while (0)
 # define trace_preempt_off(a0, a1)		do { } while (0)

commit d49dbf33f0bf8748ee3662b973eb57e60525d622
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri May 16 10:41:53 2008 +0200

    ftrace: fix include file dependency
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 017ab44d572a..911d5d80b49f 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -4,6 +4,7 @@
 #ifdef CONFIG_FTRACE
 
 #include <linux/linkage.h>
+#include <linux/fs.h>
 
 extern int ftrace_enabled;
 extern int

commit 2d8b820b2e81954754277723379ae9ed5de316fa
Author: Ingo Molnar <mingo@elte.hu>
Date:   Sat Feb 23 16:55:50 2008 +0100

    ftrace: cleanups
    
    factor out code and clean it up.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index a3e47f43f8a0..89bd9a6f52ec 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -18,13 +18,13 @@
 #include <linux/kallsyms.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
-#include <linux/kthread.h>
 #include <linux/hardirq.h>
-#include <linux/ftrace.h>
+#include <linux/kthread.h>
 #include <linux/uaccess.h>
+#include <linux/ftrace.h>
 #include <linux/sysctl.h>
-#include <linux/hash.h>
 #include <linux/ctype.h>
+#include <linux/hash.h>
 #include <linux/list.h>
 
 #include "trace.h"

commit 37135677e653537ffc6e7def679443272a1c03c3
Author: Ingo Molnar <mingo@elte.hu>
Date:   Wed May 14 08:10:31 2008 +0200

    ftrace: fix mcount export bug
    
    David S. Miller noticed the following bug: the -pg instrumentation
    function callback is named differently on each platform. On x86 it
    is mcount, on sparc it is _mcount. So the export does not make sense
    in kernel/trace/ftrace.c - move it to x86.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
index deb43785e923..29999dbb754c 100644
--- a/arch/x86/kernel/i386_ksyms_32.c
+++ b/arch/x86/kernel/i386_ksyms_32.c
@@ -1,7 +1,14 @@
+#include <linux/ftrace.h>
 #include <linux/module.h>
+
 #include <asm/checksum.h>
-#include <asm/desc.h>
 #include <asm/pgtable.h>
+#include <asm/desc.h>
+
+#ifdef CONFIG_FTRACE
+/* mcount is defined in assembly */
+EXPORT_SYMBOL(mcount);
+#endif
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index f6c05d0410fb..122885bc5f3b 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -1,15 +1,22 @@
 /* Exports for assembly files.
    All C exports should go in the respective C files. */
 
+#include <linux/ftrace.h>
 #include <linux/module.h>
-#include <net/checksum.h>
 #include <linux/smp.h>
 
+#include <net/checksum.h>
+
 #include <asm/processor.h>
-#include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/uaccess.h>
 #include <asm/desc.h>
 
+#ifdef CONFIG_FTRACE
+/* mcount is defined in assembly */
+EXPORT_SYMBOL(mcount);
+#endif
+
 EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(__get_user_1);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 07b2a14943f8..a3e47f43f8a0 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -50,9 +50,6 @@ static struct ftrace_ops ftrace_list_end __read_mostly =
 static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
 
-/* mcount is defined per arch in assembly */
-EXPORT_SYMBOL(mcount);
-
 void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
 {
 	struct ftrace_ops *op = ftrace_list;

commit 74f4e369fc5b52433ad824cef32d3bf1304549be
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon May 12 21:21:15 2008 +0200

    ftrace: stacktrace fix
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 0d3714e7110b..017ab44d572a 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -120,4 +120,12 @@ static inline void tracer_disable(void)
 # define trace_preempt_off(a0, a1)		do { } while (0)
 #endif
 
+#ifdef CONFIG_CONTEXT_SWITCH_TRACER
+extern void
+ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3);
+#else
+static inline void
+ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
+#endif
+
 #endif /* _LINUX_FTRACE_H */
diff --git a/kernel/semaphore.c b/kernel/semaphore.c
index 5c2942e768cd..1a064adab658 100644
--- a/kernel/semaphore.c
+++ b/kernel/semaphore.c
@@ -31,6 +31,7 @@
 #include <linux/sched.h>
 #include <linux/semaphore.h>
 #include <linux/spinlock.h>
+#include <linux/ftrace.h>
 
 static noinline void __down(struct semaphore *sem);
 static noinline int __down_interruptible(struct semaphore *sem);
@@ -53,6 +54,7 @@ void down(struct semaphore *sem)
 {
 	unsigned long flags;
 
+	ftrace_special(sem->count, 0, __LINE__);
 	spin_lock_irqsave(&sem->lock, flags);
 	if (likely(sem->count > 0))
 		sem->count--;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 2824cf48cdca..3271916ff033 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -901,7 +901,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
 	entry->ctx.next_pid	= next->pid;
 	entry->ctx.next_prio	= next->prio;
 	entry->ctx.next_state	= next->state;
-	__trace_stack(tr, data, flags, 4);
+	__trace_stack(tr, data, flags, 5);
 	__raw_spin_unlock(&data->lock);
 	raw_local_irq_restore(irq_flags);
 }
@@ -927,7 +927,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
 	entry->ctx.next_pid	= wakee->pid;
 	entry->ctx.next_prio	= wakee->prio;
 	entry->ctx.next_state	= wakee->state;
-	__trace_stack(tr, data, flags, 5);
+	__trace_stack(tr, data, flags, 6);
 	__raw_spin_unlock(&data->lock);
 	raw_local_irq_restore(irq_flags);
 
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index f5de0601b408..c460e85e94ed 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -51,7 +51,7 @@ struct special_entry {
  * Stack-trace entry:
  */
 
-#define FTRACE_STACK_ENTRIES	5
+#define FTRACE_STACK_ENTRIES	8
 
 struct stack_entry {
 	unsigned long		caller[FTRACE_STACK_ENTRIES];

commit a4feb8348b62fe76a63cdb5569f5c920f5283c06
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon May 12 21:21:02 2008 +0200

    ftrace: special stacktrace
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ca0d6ff74c11..c232d8248a09 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -808,29 +808,6 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data,
 		trace_function(tr, data, ip, parent_ip, flags);
 }
 
-void
-__trace_special(void *__tr, void *__data,
-		unsigned long arg1, unsigned long arg2, unsigned long arg3)
-{
-	struct trace_array_cpu *data = __data;
-	struct trace_array *tr = __tr;
-	struct trace_entry *entry;
-	unsigned long irq_flags;
-
-	raw_local_irq_save(irq_flags);
-	__raw_spin_lock(&data->lock);
-	entry			= tracing_get_trace_entry(tr, data);
-	tracing_generic_entry_update(entry, 0);
-	entry->type		= TRACE_SPECIAL;
-	entry->special.arg1	= arg1;
-	entry->special.arg2	= arg2;
-	entry->special.arg3	= arg3;
-	__raw_spin_unlock(&data->lock);
-	raw_local_irq_restore(irq_flags);
-
-	trace_wake_up();
-}
-
 void __trace_stack(struct trace_array *tr,
 		   struct trace_array_cpu *data,
 		   unsigned long flags,
@@ -856,6 +833,30 @@ void __trace_stack(struct trace_array *tr,
 	save_stack_trace(&trace);
 }
 
+void
+__trace_special(void *__tr, void *__data,
+		unsigned long arg1, unsigned long arg2, unsigned long arg3)
+{
+	struct trace_array_cpu *data = __data;
+	struct trace_array *tr = __tr;
+	struct trace_entry *entry;
+	unsigned long irq_flags;
+
+	raw_local_irq_save(irq_flags);
+	__raw_spin_lock(&data->lock);
+	entry			= tracing_get_trace_entry(tr, data);
+	tracing_generic_entry_update(entry, 0);
+	entry->type		= TRACE_SPECIAL;
+	entry->special.arg1	= arg1;
+	entry->special.arg2	= arg2;
+	entry->special.arg3	= arg3;
+	__trace_stack(tr, data, irq_flags, 4);
+	__raw_spin_unlock(&data->lock);
+	raw_local_irq_restore(irq_flags);
+
+	trace_wake_up();
+}
+
 void
 tracing_sched_switch_trace(struct trace_array *tr,
 			   struct trace_array_cpu *data,

commit 9fe068e92f6290e89e19adc521441661a1229f00
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon May 12 21:21:02 2008 +0200

    ftrace: trace faster
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 49e16630628a..ca0d6ff74c11 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2417,8 +2417,8 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
 
 		mutex_unlock(&trace_types_lock);
 
-		/* sleep for one second, and try again. */
-		schedule_timeout(HZ);
+		/* sleep for 100 msecs, and try again. */
+		schedule_timeout(HZ/10);
 
 		mutex_lock(&trace_types_lock);
 

commit afc2abc0ae4265730a0fc48618012193a09a1d10
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon May 12 21:21:00 2008 +0200

    ftrace: cleanups
    
    no code changed.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 627e39936ea7..d6b60576f991 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1155,12 +1155,12 @@ lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
 
 	hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
 	softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
-	if (hardirq && softirq)
+	if (hardirq && softirq) {
 		trace_seq_putc(s, 'H');
-	else {
-		if (hardirq)
+	} else {
+		if (hardirq) {
 			trace_seq_putc(s, 'h');
-		else {
+		} else {
 			if (softirq)
 				trace_seq_putc(s, 's');
 			else
@@ -2177,8 +2177,7 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table)
 		 * Always select as readable when in blocking mode
 		 */
 		return POLLIN | POLLRDNORM;
-	}
-	else {
+	} else {
 		if (!trace_empty(iter))
 			return POLLIN | POLLRDNORM;
 		poll_wait(filp, &trace_wait, poll_table);