From f76e9154736e9ab47b64940d0062f19c80225b7f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 24 Apr 2008 01:31:46 -0400 Subject: [ARM] latencytop support Available for !SMP only at the moment. From Russell: |Basically, if a thread is running on a CPU, thread_saved_fp() is invalid. |So, the question is: what guarantees do we have here that 'tsk' is not |running on another CPU? Signed-off-by: Nicolas Pitre Tested-by: Lennert Buytenhek Signed-off-by: Lennert Buytenhek --- arch/arm/kernel/stacktrace.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'arch/arm/kernel/stacktrace.c') diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index ae31deb2d065..90e0c35ae60d 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -36,6 +36,7 @@ EXPORT_SYMBOL(walk_stackframe); #ifdef CONFIG_STACKTRACE struct stack_trace_data { struct stack_trace *trace; + unsigned int no_sched_functions; unsigned int skip; }; @@ -43,27 +44,52 @@ static int save_trace(struct stackframe *frame, void *d) { struct stack_trace_data *data = d; struct stack_trace *trace = data->trace; + unsigned long addr = frame->lr; + if (data->no_sched_functions && in_sched_functions(addr)) + return 0; if (data->skip) { data->skip--; return 0; } - trace->entries[trace->nr_entries++] = frame->lr; + trace->entries[trace->nr_entries++] = addr; return trace->nr_entries >= trace->max_entries; } -void save_stack_trace(struct stack_trace *trace) +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; unsigned long fp, base; data.trace = trace; data.skip = trace->skip; - base = (unsigned long)task_stack_page(current); - asm("mov %0, fp" : "=r" (fp)); + base = (unsigned long)task_stack_page(tsk); + + if (tsk != current) { +#ifdef CONFIG_SMP + /* + * What guarantees do we have here that 'tsk' + * is not running on another CPU? + */ + BUG(); +#else + data.no_sched_functions = 1; + fp = thread_saved_fp(tsk); +#endif + } else { + data.no_sched_functions = 0; + asm("mov %0, fp" : "=r" (fp)); + } walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} + +void save_stack_trace(struct stack_trace *trace) +{ + save_stack_trace_tsk(current, trace); } #endif -- cgit v1.2.3 From 7b4c9505f2fd82b117dd015b561f723b9a5dab79 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 3 Jul 2008 09:17:55 +0200 Subject: stacktrace: export save_stack_trace[_tsk] Andrew Morton reported this against linux-next: ERROR: ".save_stack_trace" [tests/backtracetest.ko] undefined! Reported-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/arm/kernel/stacktrace.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/kernel/stacktrace.c') diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index ae31deb2d065..6b3ffde5deaa 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -66,4 +66,5 @@ void save_stack_trace(struct stack_trace *trace) walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data); } +EXPORT_SYMBOL_GPL(save_stack_trace); #endif -- cgit v1.2.3