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 0eae00b3e58..c7ea7f2a894 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; +}  |