Merge branch 'sh/dwarf-unwinder' of git://github.com/mfleming/linux-2.6 into sh/dwarf-unwinder

This commit is contained in:
Paul Mundt
2009-08-22 03:49:58 +09:00
10 changed files with 252 additions and 105 deletions

View File

@@ -54,8 +54,6 @@ static struct list_head unwinder_list = {
static DEFINE_SPINLOCK(unwinder_lock);
static atomic_t unwinder_running = ATOMIC_INIT(0);
/**
* select_unwinder - Select the best registered stack unwinder.
*
@@ -123,6 +121,8 @@ int unwinder_register(struct unwinder *u)
return ret;
}
int unwinder_faulted = 0;
/*
* Unwind the call stack and pass information to the stacktrace_ops
* functions. Also handle the case where we need to switch to a new
@@ -145,20 +145,41 @@ void unwind_stack(struct task_struct *task, struct pt_regs *regs,
* Hopefully this will give us a semi-reliable stacktrace so we
* can diagnose why curr_unwinder->dump() faulted.
*/
if (atomic_inc_return(&unwinder_running) != 1) {
if (unwinder_faulted) {
spin_lock_irqsave(&unwinder_lock, flags);
if (!list_is_singular(&unwinder_list)) {
/* Make sure no one beat us to changing the unwinder */
if (unwinder_faulted && !list_is_singular(&unwinder_list)) {
list_del(&curr_unwinder->list);
curr_unwinder = select_unwinder();
unwinder_faulted = 0;
}
spin_unlock_irqrestore(&unwinder_lock, flags);
atomic_dec(&unwinder_running);
}
curr_unwinder->dump(task, regs, sp, ops, data);
}
atomic_dec(&unwinder_running);
/*
* Trap handler for UWINDER_BUG() statements. We must switch to the
* unwinder with the next highest rating.
*/
BUILD_TRAP_HANDLER(unwinder)
{
insn_size_t insn;
TRAP_HANDLER_DECL;
/* Rewind */
regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
insn = *(insn_size_t *)instruction_pointer(regs);
/* Switch unwinders when unwind_stack() is called */
unwinder_faulted = 1;
#ifdef CONFIG_BUG
handle_BUG(regs);
#endif
}
EXPORT_SYMBOL_GPL(unwind_stack);