diff options
-rw-r--r-- | arch/um/kernel/process.c | 35 | ||||
-rw-r--r-- | include/asm-um/processor-generic.h | 2 |
2 files changed, 36 insertions, 1 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 | } | ||
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index 78c0599cc80c..057a76d41569 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h | |||
@@ -128,6 +128,6 @@ extern struct cpuinfo_um cpu_data[]; | |||
128 | 128 | ||
129 | 129 | ||
130 | #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf) | 130 | #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf) |
131 | #define get_wchan(p) (0) | 131 | extern unsigned long get_wchan(struct task_struct *p); |
132 | 132 | ||
133 | #endif | 133 | #endif |