aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2008-04-24 01:31:46 -0400
committerLennert Buytenhek <buytenh@marvell.com>2008-06-22 16:44:36 -0400
commitf76e9154736e9ab47b64940d0062f19c80225b7f (patch)
treeeb8a909667362fc552894d7987ff3e57ade4fa0f /arch/arm
parentb0bfcce930bca38af056662e598991cb393eaa4a (diff)
[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 <nico@marvell.com> Tested-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig5
-rw-r--r--arch/arm/kernel/stacktrace.c34
2 files changed, 35 insertions, 4 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b786e68914d..a91b9ac9a0e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -84,6 +84,11 @@ config STACKTRACE_SUPPORT
84 bool 84 bool
85 default y 85 default y
86 86
87config HAVE_LATENCYTOP_SUPPORT
88 bool
89 depends on !SMP
90 default y
91
87config LOCKDEP_SUPPORT 92config LOCKDEP_SUPPORT
88 bool 93 bool
89 default y 94 default y
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index ae31deb2d06..90e0c35ae60 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -36,6 +36,7 @@ EXPORT_SYMBOL(walk_stackframe);
36#ifdef CONFIG_STACKTRACE 36#ifdef CONFIG_STACKTRACE
37struct stack_trace_data { 37struct stack_trace_data {
38 struct stack_trace *trace; 38 struct stack_trace *trace;
39 unsigned int no_sched_functions;
39 unsigned int skip; 40 unsigned int skip;
40}; 41};
41 42
@@ -43,27 +44,52 @@ static int save_trace(struct stackframe *frame, void *d)
43{ 44{
44 struct stack_trace_data *data = d; 45 struct stack_trace_data *data = d;
45 struct stack_trace *trace = data->trace; 46 struct stack_trace *trace = data->trace;
47 unsigned long addr = frame->lr;
46 48
49 if (data->no_sched_functions && in_sched_functions(addr))
50 return 0;
47 if (data->skip) { 51 if (data->skip) {
48 data->skip--; 52 data->skip--;
49 return 0; 53 return 0;
50 } 54 }
51 55
52 trace->entries[trace->nr_entries++] = frame->lr; 56 trace->entries[trace->nr_entries++] = addr;
53 57
54 return trace->nr_entries >= trace->max_entries; 58 return trace->nr_entries >= trace->max_entries;
55} 59}
56 60
57void save_stack_trace(struct stack_trace *trace) 61void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
58{ 62{
59 struct stack_trace_data data; 63 struct stack_trace_data data;
60 unsigned long fp, base; 64 unsigned long fp, base;
61 65
62 data.trace = trace; 66 data.trace = trace;
63 data.skip = trace->skip; 67 data.skip = trace->skip;
64 base = (unsigned long)task_stack_page(current); 68 base = (unsigned long)task_stack_page(tsk);
65 asm("mov %0, fp" : "=r" (fp)); 69
70 if (tsk != current) {
71#ifdef CONFIG_SMP
72 /*
73 * What guarantees do we have here that 'tsk'
74 * is not running on another CPU?
75 */
76 BUG();
77#else
78 data.no_sched_functions = 1;
79 fp = thread_saved_fp(tsk);
80#endif
81 } else {
82 data.no_sched_functions = 0;
83 asm("mov %0, fp" : "=r" (fp));
84 }
66 85
67 walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data); 86 walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
87 if (trace->nr_entries < trace->max_entries)
88 trace->entries[trace->nr_entries++] = ULONG_MAX;
89}
90
91void save_stack_trace(struct stack_trace *trace)
92{
93 save_stack_trace_tsk(current, trace);
68} 94}
69#endif 95#endif