diff options
Diffstat (limited to 'arch/um/kernel/process.c')
-rw-r--r-- | arch/um/kernel/process.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 0eae00b3e588..c7ea7f2a8945 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -459,3 +459,38 @@ unsigned long arch_align_stack(unsigned long sp) return sp & ~0xf; } #endif + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long stack_page, sp, ip; + bool seen_sched = 0; + + if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING)) + return 0; + + stack_page = (unsigned long) task_stack_page(p); + /* Bail if the process has no kernel stack for some reason */ + if (stack_page == 0) + return 0; + + sp = p->thread.switch_buf->JB_SP; + /* + * Bail if the stack pointer is below the bottom of the kernel + * stack for some reason + */ + if (sp < stack_page) + return 0; + + while (sp < stack_page + THREAD_SIZE) { + ip = *((unsigned long *) sp); + if (in_sched_functions(ip)) + /* Ignore everything until we're above the scheduler */ + seen_sched = 1; + else if (kernel_text_address(ip) && seen_sched) + return ip; + + sp += sizeof(unsigned long); + } + + return 0; +} |