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) | |||
459 | return sp & ~0xf; | 459 | return sp & ~0xf; |
460 | } | 460 | } |
461 | #endif | 461 | #endif |
462 | |||
463 | unsigned 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 | } | ||