diff options
Diffstat (limited to 'arch/mips/kernel/stacktrace.c')
| -rw-r--r-- | arch/mips/kernel/stacktrace.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 1ba775d24d38..506021f62549 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c | |||
| @@ -12,14 +12,15 @@ | |||
| 12 | * Save stack-backtrace addresses into a stack_trace buffer: | 12 | * Save stack-backtrace addresses into a stack_trace buffer: |
| 13 | */ | 13 | */ |
| 14 | static void save_raw_context_stack(struct stack_trace *trace, | 14 | static void save_raw_context_stack(struct stack_trace *trace, |
| 15 | unsigned long reg29) | 15 | unsigned long reg29, int savesched) |
| 16 | { | 16 | { |
| 17 | unsigned long *sp = (unsigned long *)reg29; | 17 | unsigned long *sp = (unsigned long *)reg29; |
| 18 | unsigned long addr; | 18 | unsigned long addr; |
| 19 | 19 | ||
| 20 | while (!kstack_end(sp)) { | 20 | while (!kstack_end(sp)) { |
| 21 | addr = *sp++; | 21 | addr = *sp++; |
| 22 | if (__kernel_text_address(addr)) { | 22 | if (__kernel_text_address(addr) && |
| 23 | (savesched || !in_sched_functions(addr))) { | ||
| 23 | if (trace->skip > 0) | 24 | if (trace->skip > 0) |
| 24 | trace->skip--; | 25 | trace->skip--; |
| 25 | else | 26 | else |
| @@ -31,7 +32,7 @@ static void save_raw_context_stack(struct stack_trace *trace, | |||
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | static void save_context_stack(struct stack_trace *trace, | 34 | static void save_context_stack(struct stack_trace *trace, |
| 34 | struct task_struct *tsk, struct pt_regs *regs) | 35 | struct task_struct *tsk, struct pt_regs *regs, int savesched) |
| 35 | { | 36 | { |
| 36 | unsigned long sp = regs->regs[29]; | 37 | unsigned long sp = regs->regs[29]; |
| 37 | #ifdef CONFIG_KALLSYMS | 38 | #ifdef CONFIG_KALLSYMS |
| @@ -43,20 +44,22 @@ static void save_context_stack(struct stack_trace *trace, | |||
| 43 | (unsigned long)task_stack_page(tsk); | 44 | (unsigned long)task_stack_page(tsk); |
| 44 | if (stack_page && sp >= stack_page && | 45 | if (stack_page && sp >= stack_page && |
| 45 | sp <= stack_page + THREAD_SIZE - 32) | 46 | sp <= stack_page + THREAD_SIZE - 32) |
| 46 | save_raw_context_stack(trace, sp); | 47 | save_raw_context_stack(trace, sp, savesched); |
| 47 | return; | 48 | return; |
| 48 | } | 49 | } |
| 49 | do { | 50 | do { |
| 50 | if (trace->skip > 0) | 51 | if (savesched || !in_sched_functions(pc)) { |
| 51 | trace->skip--; | 52 | if (trace->skip > 0) |
| 52 | else | 53 | trace->skip--; |
| 53 | trace->entries[trace->nr_entries++] = pc; | 54 | else |
| 54 | if (trace->nr_entries >= trace->max_entries) | 55 | trace->entries[trace->nr_entries++] = pc; |
| 55 | break; | 56 | if (trace->nr_entries >= trace->max_entries) |
| 57 | break; | ||
| 58 | } | ||
| 56 | pc = unwind_stack(tsk, &sp, pc, &ra); | 59 | pc = unwind_stack(tsk, &sp, pc, &ra); |
| 57 | } while (pc); | 60 | } while (pc); |
| 58 | #else | 61 | #else |
| 59 | save_raw_context_stack(trace, sp); | 62 | save_raw_context_stack(trace, sp, savesched); |
| 60 | #endif | 63 | #endif |
| 61 | } | 64 | } |
| 62 | 65 | ||
| @@ -82,6 +85,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | |||
| 82 | regs->cp0_epc = tsk->thread.reg31; | 85 | regs->cp0_epc = tsk->thread.reg31; |
| 83 | } else | 86 | } else |
| 84 | prepare_frametrace(regs); | 87 | prepare_frametrace(regs); |
| 85 | save_context_stack(trace, tsk, regs); | 88 | save_context_stack(trace, tsk, regs, tsk == current); |
| 86 | } | 89 | } |
| 87 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); | 90 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |
