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