aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/process.c')
-rw-r--r--arch/um/kernel/process.c35
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)
459 return sp & ~0xf; 459 return sp & ~0xf;
460} 460}
461#endif 461#endif
462
463unsigned long get_wchan(struct task_struct *p)
464{
465 unsigned long stack_page, sp, ip;
466 bool seen_sched = 0;
467
468 if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
469 return 0;
470
471 stack_page = (unsigned long) task_stack_page(p);
472 /* Bail if the process has no kernel stack for some reason */
473 if (stack_page == 0)
474 return 0;
475
476 sp = p->thread.switch_buf->JB_SP;
477 /*
478 * Bail if the stack pointer is below the bottom of the kernel
479 * stack for some reason
480 */
481 if (sp < stack_page)
482 return 0;
483
484 while (sp < stack_page + THREAD_SIZE) {
485 ip = *((unsigned long *) sp);
486 if (in_sched_functions(ip))
487 /* Ignore everything until we're above the scheduler */
488 seen_sched = 1;
489 else if (kernel_text_address(ip) && seen_sched)
490 return ip;
491
492 sp += sizeof(unsigned long);
493 }
494
495 return 0;
496}