From: Mark Wielaard Date: Mon, 26 Sep 2011 14:19:37 +0000 (+0200) Subject: stack.c (_stp_get_uregs): Detect kernel unwind before user unwind case. X-Git-Tag: release-1.7~151^2~138 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=639718028ab729b8e72c5555ca9a79317f89fd76;p=systemtap.git stack.c (_stp_get_uregs): Detect kernel unwind before user unwind case. Detect and optimize the kernel backtrace() then user backtrace in same probe case, by reusing the unwind info. --- diff --git a/runtime/stack.c b/runtime/stack.c index fb78781cf..947e201dd 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -166,14 +166,27 @@ static struct pt_regs *_stp_get_uregs(struct context *c) else if (c->uregs != NULL && c->kregs != NULL && ! (c->probe_flags & _STP_PROBE_STATE_USER_MODE)) { - /* Try to recover the uregs by unwinding from the the kernel - probe location. */ struct unwind_frame_info *info = &c->uwcontext.info; - int levels = MAXBACKTRACE; int ret = 0; - arch_unw_init_frame_info(info, c->kregs, 0); - dbug_unwind(1, "Trying to recover... searching for 0x%lx\n", - REG_IP(c->uregs)); + int levels; + + /* We might be lucky and this probe already ran the kernel + unwind to end up in the user regs. */ + if (UNW_PC(info) == REG_IP(c->uregs)) + { + levels = 0; + dbug_unwind(1, "feeling lucky, info pc == uregs pc\n"); + } + else + { + /* Try to recover the uregs by unwinding from the the kernel + probe location. */ + levels = MAXBACKTRACE; + arch_unw_init_frame_info(info, c->kregs, 0); + dbug_unwind(1, "Trying to recover... searching for 0x%lx\n", + REG_IP(c->uregs)); + } + while (levels > 0 && ret == 0 && UNW_PC(info) != REG_IP(c->uregs)) { levels--; @@ -183,7 +196,7 @@ static struct pt_regs *_stp_get_uregs(struct context *c) } /* Have we arrived where we think user space currently is? */ - if (ret == 0 && UNW_PC(info) == REG_IP(_stp_current_pt_regs())) + if (ret == 0 && UNW_PC(info) == REG_IP(c->uregs)) { /* Note we need to clear this state again when the unwinder has been rerun. See __stp_stack_print invocation below. */