Beispiel #1
0
unsigned long get_wchan(struct task_struct *p)
{
	unsigned long fp, lr;
	unsigned long stack_page;
	int count = 0;
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;

	stack_page = 4096 + (unsigned long)p;
	fp = thread_saved_fp(p);
	do {
		if (fp < stack_page || fp > 4092+stack_page)
			return 0;
		lr = pc_pointer (((unsigned long *)fp)[-1]);
		if (!in_sched_functions(lr))
			return lr;
		fp = *(unsigned long *) (fp - 12);
	} while (count ++ < 16);
	return 0;
}
Beispiel #2
0
static unsigned long get_wchan(struct task_struct *p)
{
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;
#if defined(__i386__)
	{
		unsigned long ebp, esp, eip;
		unsigned long stack_page;
		int count = 0;

		stack_page = (unsigned long)p;
		esp = p->tss.esp;
		if (!stack_page || esp < stack_page || esp >= 8188+stack_page)
			return 0;
		/* include/asm-i386/system.h:switch_to() pushes ebp last. */
		ebp = *(unsigned long *) esp;
		do {
			if (ebp < stack_page || ebp >= 8188+stack_page)
				return 0;
			eip = *(unsigned long *) (ebp+4);
			if (eip < first_sched || eip >= last_sched)
				return eip;
			ebp = *(unsigned long *) ebp;
		} while (count++ < 16);
	}
#elif defined(__alpha__)
	/*
	 * This one depends on the frame size of schedule().  Do a
	 * "disass schedule" in gdb to find the frame size.  Also, the
	 * code assumes that sleep_on() follows immediately after
	 * interruptible_sleep_on() and that add_timer() follows
	 * immediately after interruptible_sleep().  Ugly, isn't it?
	 * Maybe adding a wchan field to task_struct would be better,
	 * after all...
	 */
	{
	    unsigned long schedule_frame;
	    unsigned long pc;

	    pc = thread_saved_pc(&p->tss);
	    if (pc >= first_sched && pc < last_sched) {
		schedule_frame = ((unsigned long *)p->tss.ksp)[6];
		return ((unsigned long *)schedule_frame)[12];
	    }
	    return pc;
	}
#elif defined(__mips__)
	/*
	 * The same comment as on the Alpha applies here, too ...
	 */
	{
		unsigned long schedule_frame;
		unsigned long pc;

		pc = thread_saved_pc(&p->tss);
		if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
			schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16];
			return (unsigned long)((unsigned long *)schedule_frame)[11];
		}
		return pc;
	}
#elif defined(__mc68000__)
	{
	    unsigned long fp, pc;
	    unsigned long stack_page;
	    int count = 0;

	    stack_page = (unsigned long)p;
	    fp = ((struct switch_stack *)p->tss.ksp)->a6;
	    do {
		    if (fp < stack_page+sizeof(struct task_struct) ||
			fp >= 8184+stack_page)
			    return 0;
		    pc = ((unsigned long *)fp)[1];
		/* FIXME: This depends on the order of these functions. */
		    if (pc < first_sched || pc >= last_sched)
		      return pc;
		    fp = *(unsigned long *) fp;
	    } while (count++ < 16);
	}
#elif defined(__powerpc__)
	{
		unsigned long ip, sp;
		unsigned long stack_page = (unsigned long) p;
		int count = 0;

		sp = p->tss.ksp;
		do {
			sp = *(unsigned long *)sp;
			if (sp < stack_page || sp >= stack_page + 8188)
				return 0;
			if (count > 0) {
				ip = *(unsigned long *)(sp + 4);
				if (ip < first_sched || ip >= last_sched)
					return ip;
			}
		} while (count++ < 16);
	}
#elif defined(__arm__)
	{
		unsigned long fp, lr;
		unsigned long stack_page;
		int count = 0;

		stack_page = 4096 + (unsigned long)p;
		fp = get_css_fp (&p->tss);
		do {
			if (fp < stack_page || fp > 4092+stack_page)
				return 0;
			lr = pc_pointer (((unsigned long *)fp)[-1]);
			if (lr < first_sched || lr > last_sched)
				return lr;
			fp = *(unsigned long *) (fp - 12);
		} while (count ++ < 16);
	}
#elif defined (__sparc__)
	{
		unsigned long pc, fp, bias = 0;
		unsigned long task_base = (unsigned long) p;
		struct reg_window *rw;
		int count = 0;

#ifdef __sparc_v9__
		bias = STACK_BIAS;
#endif
		fp = p->tss.ksp + bias;
		do {
			/* Bogus frame pointer? */
			if (fp < (task_base + sizeof(struct task_struct)) ||
			    fp >= (task_base + (2 * PAGE_SIZE)))
				break;
			rw = (struct reg_window *) fp;
			pc = rw->ins[7];
			if (pc < first_sched || pc >= last_sched)
				return pc;
			fp = rw->ins[6] + bias;
		} while (++count < 16);
	}
#elif defined (__s390__)
        {
                unsigned long ksp, backchain, ip;
                unsigned long stack_page;
                int count = 0;

                stack_page = (unsigned long)p;
                ksp = p->tss.ksp;
                if (!stack_page || ksp < stack_page || ksp >= 8188+stack_page)
                        return 0;
                backchain = (*(unsigned long *) ksp) & 0x7fffffff;
                do {
                        if (backchain < stack_page || backchain >= 8188+stack_page)
                                return 0;
                        ip = (*(unsigned long *) (backchain+56)) & 0x7fffffff;
                        if (ip < first_sched || ip >= last_sched)
                                return ip;
                        backchain = (*(unsigned long *) backchain) & 0x7fffffff;
                } while (count++ < 16);
        }
#endif

	return 0;
}