Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 36051
b: refs/heads/master
c: b594318
h: refs/heads/master
i:
  36049: e37fe15
  36047: e1410dc
v: v3
  • Loading branch information
Franck Bui-Huu authored and Ralf Baechle committed Sep 27, 2006
1 parent b1dbc72 commit 66d51a8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 83 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 29b376ff10aaea69ee4d93b70d0fbb2ebfd80f4e
refs/heads/master: b5943182592ba256639a569c7d5305cf60360733
132 changes: 50 additions & 82 deletions trunk/arch/mips/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,15 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
}

static struct mips_frame_info {
void *func;
unsigned long func_size;
int frame_size;
int pc_offset;
} *schedule_frame, mfinfo[64];
static int mfinfo_num;
/*
*
*/
struct mips_frame_info {
void *func;
unsigned long func_size;
int frame_size;
int pc_offset;
};

static inline int is_ra_save_ins(union mips_instruction *ip)
{
Expand Down Expand Up @@ -348,45 +350,30 @@ static int get_frame_info(struct mips_frame_info *info)
return -1;
}

static struct mips_frame_info schedule_mfi __read_mostly;

static int __init frame_info_init(void)
{
int i;
unsigned long size = 0;
#ifdef CONFIG_KALLSYMS
unsigned long ofs;
char *modname;
char namebuf[KSYM_NAME_LEN + 1];
unsigned long start, size, ofs;
extern char __sched_text_start[], __sched_text_end[];
extern char __lock_text_start[], __lock_text_end[];

start = (unsigned long)__sched_text_start;
for (i = 0; i < ARRAY_SIZE(mfinfo); i++) {
if (start == (unsigned long)schedule)
schedule_frame = &mfinfo[i];
if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf))
break;
mfinfo[i].func = (void *)(start + ofs);
mfinfo[i].func_size = size;
start += size - ofs;
if (start >= (unsigned long)__lock_text_end)
break;
if (start == (unsigned long)__sched_text_end)
start = (unsigned long)__lock_text_start;
}
#else
mfinfo[0].func = schedule;
schedule_frame = &mfinfo[0];

kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf);
#endif
for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++)
get_frame_info(mfinfo + i);
schedule_mfi.func = schedule;
schedule_mfi.func_size = size;

get_frame_info(&schedule_mfi);

/*
* Without schedule() frame info, result given by
* thread_saved_pc() and get_wchan() are not reliable.
*/
if (schedule_frame->pc_offset < 0)
if (schedule_mfi.pc_offset < 0)
printk("Can't analyze schedule() prologue at %p\n", schedule);

mfinfo_num = i;
return 0;
}

Expand All @@ -402,58 +389,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
/* New born processes are a special case */
if (t->reg31 == (unsigned long) ret_from_fork)
return t->reg31;

if (!schedule_frame || schedule_frame->pc_offset < 0)
if (schedule_mfi.pc_offset < 0)
return 0;
return ((unsigned long *)t->reg29)[schedule_frame->pc_offset];
return ((unsigned long *)t->reg29)[schedule_mfi.pc_offset];
}

/* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */
unsigned long get_wchan(struct task_struct *p)
{
unsigned long stack_page;
unsigned long pc;
#ifdef CONFIG_KALLSYMS
unsigned long frame;
#endif

if (!p || p == current || p->state == TASK_RUNNING)
return 0;

stack_page = (unsigned long)task_stack_page(p);
if (!stack_page || !mfinfo_num)
return 0;

pc = thread_saved_pc(p);
#ifdef CONFIG_KALLSYMS
if (!in_sched_functions(pc))
return pc;

frame = p->thread.reg29 + schedule_frame->frame_size;
do {
int i;

if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
return 0;

for (i = mfinfo_num - 1; i >= 0; i--) {
if (pc >= (unsigned long) mfinfo[i].func)
break;
}
if (i < 0)
break;

if (mfinfo[i].pc_offset < 0)
break;
pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
if (!mfinfo[i].frame_size)
break;
frame += mfinfo[i].frame_size;
} while (in_sched_functions(pc));
#endif

return pc;
}

#ifdef CONFIG_KALLSYMS
/* used by show_backtrace() */
Expand Down Expand Up @@ -504,3 +444,31 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
return __kernel_text_address(pc) ? pc : 0;
}
#endif

/*
* get_wchan - a maintenance nightmare^W^Wpain in the ass ...
*/
unsigned long get_wchan(struct task_struct *task)
{
unsigned long pc = 0;
#ifdef CONFIG_KALLSYMS
unsigned long sp;
#endif

if (!task || task == current || task->state == TASK_RUNNING)
goto out;
if (!task_stack_page(task))
goto out;

pc = thread_saved_pc(task);

#ifdef CONFIG_KALLSYMS
sp = task->thread.reg29 + schedule_mfi.frame_size;

while (in_sched_functions(pc))
pc = unwind_stack(task, &sp, pc, 0);
#endif

out:
return pc;
}

0 comments on commit 66d51a8

Please sign in to comment.