aboutsummaryrefslogtreecommitdiff
path: root/arch/csky/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/csky/kernel/process.c')
-rw-r--r--arch/csky/kernel/process.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c
index 8ed20028b160..e555740c0be5 100644
--- a/arch/csky/kernel/process.c
+++ b/arch/csky/kernel/process.c
@@ -93,26 +93,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
unsigned long get_wchan(struct task_struct *p)
{
- unsigned long esp, pc;
- unsigned long stack_page;
+ unsigned long lr;
+ unsigned long *fp, *stack_start, *stack_end;
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = (unsigned long)p;
- esp = p->thread.esp0;
+ stack_start = (unsigned long *)end_of_stack(p);
+ stack_end = (unsigned long *)(task_stack_page(p) + THREAD_SIZE);
+
+ fp = (unsigned long *) thread_saved_fp(p);
do {
- if (esp < stack_page+sizeof(struct task_struct) ||
- esp >= 8184+stack_page)
+ if (fp < stack_start || fp > stack_end)
return 0;
- /*FIXME: There's may be error here!*/
- pc = ((unsigned long *)esp)[1];
- /* FIXME: This depends on the order of these functions. */
- if (!in_sched_functions(pc))
- return pc;
- esp = *(unsigned long *) esp;
+#ifdef CONFIG_STACKTRACE
+ lr = fp[1];
+ fp = (unsigned long *)fp[0];
+#else
+ lr = *fp++;
+#endif
+ if (!in_sched_functions(lr) &&
+ __kernel_text_address(lr))
+ return lr;
} while (count++ < 16);
+
return 0;
}
EXPORT_SYMBOL(get_wchan);