diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/backtracetest.c | 65 | ||||
-rw-r--r-- | kernel/stacktrace.c | 14 |
2 files changed, 62 insertions, 17 deletions
diff --git a/kernel/backtracetest.c b/kernel/backtracetest.c index d1a7605c5b8..a5e026bc45c 100644 --- a/kernel/backtracetest.c +++ b/kernel/backtracetest.c @@ -10,30 +10,73 @@ * of the License. */ +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/sched.h> -#include <linux/delay.h> +#include <linux/stacktrace.h> + +static void backtrace_test_normal(void) +{ + printk("Testing a backtrace from process context.\n"); + printk("The following trace is a kernel self test and not a bug!\n"); -static struct timer_list backtrace_timer; + dump_stack(); +} -static void backtrace_test_timer(unsigned long data) +static DECLARE_COMPLETION(backtrace_work); + +static void backtrace_test_irq_callback(unsigned long data) +{ + dump_stack(); + complete(&backtrace_work); +} + +static DECLARE_TASKLET(backtrace_tasklet, &backtrace_test_irq_callback, 0); + +static void backtrace_test_irq(void) { printk("Testing a backtrace from irq context.\n"); printk("The following trace is a kernel self test and not a bug!\n"); - dump_stack(); + + init_completion(&backtrace_work); + tasklet_schedule(&backtrace_tasklet); + wait_for_completion(&backtrace_work); +} + +#ifdef CONFIG_STACKTRACE +static void backtrace_test_saved(void) +{ + struct stack_trace trace; + unsigned long entries[8]; + + printk("Testing a saved backtrace.\n"); + printk("The following trace is a kernel self test and not a bug!\n"); + + trace.nr_entries = 0; + trace.max_entries = ARRAY_SIZE(entries); + trace.entries = entries; + trace.skip = 0; + + save_stack_trace(&trace); + print_stack_trace(&trace, 0); +} +#else +static void backtrace_test_saved(void) +{ + printk("Saved backtrace test skipped.\n"); } +#endif + static int backtrace_regression_test(void) { printk("====[ backtrace testing ]===========\n"); - printk("Testing a backtrace from process context.\n"); - printk("The following trace is a kernel self test and not a bug!\n"); - dump_stack(); - init_timer(&backtrace_timer); - backtrace_timer.function = backtrace_test_timer; - mod_timer(&backtrace_timer, jiffies + 10); + backtrace_test_normal(); + backtrace_test_irq(); + backtrace_test_saved(); - msleep(10); printk("====[ end of backtrace testing ]====\n"); return 0; } diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c index b71816e47a3..94b527ef1d1 100644 --- a/kernel/stacktrace.c +++ b/kernel/stacktrace.c @@ -6,19 +6,21 @@ * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> */ #include <linux/sched.h> +#include <linux/module.h> #include <linux/kallsyms.h> #include <linux/stacktrace.h> void print_stack_trace(struct stack_trace *trace, int spaces) { - int i, j; + int i; - for (i = 0; i < trace->nr_entries; i++) { - unsigned long ip = trace->entries[i]; + if (WARN_ON(!trace->entries)) + return; - for (j = 0; j < spaces + 1; j++) - printk(" "); - print_ip_sym(ip); + for (i = 0; i < trace->nr_entries; i++) { + printk("%*c", 1 + spaces, ' '); + print_ip_sym(trace->entries[i]); } } +EXPORT_SYMBOL_GPL(print_stack_trace); |