Commit f76e9154 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Lennert Buytenhek

[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: default avatarNicolas Pitre <nico@marvell.com>
Tested-by: default avatarLennert Buytenhek <buytenh@marvell.com>
Signed-off-by: default avatarLennert Buytenhek <buytenh@marvell.com>
parent b0bfcce9
...@@ -84,6 +84,11 @@ config STACKTRACE_SUPPORT ...@@ -84,6 +84,11 @@ config STACKTRACE_SUPPORT
bool bool
default y default y
config HAVE_LATENCYTOP_SUPPORT
bool
depends on !SMP
default y
config LOCKDEP_SUPPORT config LOCKDEP_SUPPORT
bool bool
default y default y
......
...@@ -36,6 +36,7 @@ EXPORT_SYMBOL(walk_stackframe); ...@@ -36,6 +36,7 @@ EXPORT_SYMBOL(walk_stackframe);
#ifdef CONFIG_STACKTRACE #ifdef CONFIG_STACKTRACE
struct stack_trace_data { struct stack_trace_data {
struct stack_trace *trace; struct stack_trace *trace;
unsigned int no_sched_functions;
unsigned int skip; unsigned int skip;
}; };
...@@ -43,27 +44,52 @@ static int save_trace(struct stackframe *frame, void *d) ...@@ -43,27 +44,52 @@ static int save_trace(struct stackframe *frame, void *d)
{ {
struct stack_trace_data *data = d; struct stack_trace_data *data = d;
struct stack_trace *trace = data->trace; 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) { if (data->skip) {
data->skip--; data->skip--;
return 0; return 0;
} }
trace->entries[trace->nr_entries++] = frame->lr; trace->entries[trace->nr_entries++] = addr;
return trace->nr_entries >= trace->max_entries; 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; struct stack_trace_data data;
unsigned long fp, base; unsigned long fp, base;
data.trace = trace; data.trace = trace;
data.skip = trace->skip; data.skip = trace->skip;
base = (unsigned long)task_stack_page(current); 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)); asm("mov %0, fp" : "=r" (fp));
}
walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data); 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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment