From bac564c53e908cff16f9938320a344d62bca26a7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 24 May 2012 21:07:18 +0000 Subject: runtime: Make runtime.Stack actually work. From-SVN: r187854 --- libgo/runtime/go-traceback.c | 66 +++++++++++++++----------------------------- libgo/runtime/mprof.goc | 26 ++++++++--------- libgo/runtime/proc.c | 30 ++++++++++++++------ libgo/runtime/runtime.h | 5 +++- 4 files changed, 61 insertions(+), 66 deletions(-) diff --git a/libgo/runtime/go-traceback.c b/libgo/runtime/go-traceback.c index 2ff2ce3..4e99ca7 100644 --- a/libgo/runtime/go-traceback.c +++ b/libgo/runtime/go-traceback.c @@ -6,57 +6,37 @@ #include "config.h" -#include "unwind.h" - #include "runtime.h" #include "go-string.h" -static _Unwind_Reason_Code -traceback (struct _Unwind_Context *context, void *varg) +/* Print a stack trace for the current goroutine. */ + +void +runtime_traceback () { - int *parg = (int *) varg; - uintptr pc; - int ip_before_insn = 0; - struct __go_string fn; - struct __go_string file; - int line; - -#ifdef HAVE_GETIPINFO - pc = _Unwind_GetIPInfo (context, &ip_before_insn); -#else - pc = _Unwind_GetIP (context); -#endif - - if (*parg > 100) - return _URC_END_OF_STACK; - ++*parg; - - /* FIXME: If PC is in the __morestack routine, we should ignore - it. */ - - /* Back up to the call instruction. */ - if (!ip_before_insn) - --pc; - - if (!__go_file_line (pc, &fn, &file, &line)) - return _URC_END_OF_STACK; - - if (runtime_showframe (fn.__data)) - { - runtime_printf ("%s\n", fn.__data); - runtime_printf ("\t%s:%d\n", file.__data, line); - } + uintptr pcbuf[100]; + int32 c; - return _URC_NO_REASON; + c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]); + runtime_printtrace (pcbuf, c); } -/* Print a stack trace for the current goroutine. */ - void -runtime_traceback () +runtime_printtrace (uintptr *pcbuf, int32 c) { - int c; + int32 i; - c = 0; - _Unwind_Backtrace (traceback, &c); + for (i = 0; i < c; ++i) + { + struct __go_string fn; + struct __go_string file; + int line; + + if (__go_file_line (pcbuf[i], &fn, &file, &line) + && runtime_showframe (fn.__data)) + { + runtime_printf ("%s\n", fn.__data); + runtime_printf ("\t%s:%d\n", file.__data, line); + } + } } diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc index a8bee20..875abe3 100644 --- a/libgo/runtime/mprof.goc +++ b/libgo/runtime/mprof.goc @@ -343,6 +343,7 @@ func ThreadCreateProfile(p Slice) (n int32, ok bool) { func Stack(b Slice, all bool) (n int32) { byte *pc, *sp; + bool enablegc; sp = runtime_getcallersp(&b); pc = runtime_getcallerpc(&b); @@ -351,6 +352,8 @@ func Stack(b Slice, all bool) (n int32) { runtime_semacquire(&runtime_worldsema); runtime_m()->gcing = 1; runtime_stoptheworld(); + enablegc = mstats.enablegc; + mstats.enablegc = false; } if(b.__count == 0) @@ -373,33 +376,31 @@ func Stack(b Slice, all bool) (n int32) { if(all) { runtime_m()->gcing = 0; + mstats.enablegc = enablegc; runtime_semrelease(&runtime_worldsema); runtime_starttheworld(false); } } static void -saveg(byte *pc, byte *sp, G *g, TRecord *r) +saveg(G *g, TRecord *r) { int32 n; - USED(pc); - USED(sp); - USED(g); - // n = runtime_gentraceback(pc, sp, 0, g, 0, r->stk, nelem(r->stk)); - n = 0; + if(g == runtime_g()) + n = runtime_callers(0, r->stk, nelem(r->stk)); + else { + // FIXME: Not implemented. + n = 0; + } if((size_t)n < nelem(r->stk)) r->stk[n] = 0; } func GoroutineProfile(b Slice) (n int32, ok bool) { - byte *pc, *sp; TRecord *r; G *gp; - sp = runtime_getcallersp(&b); - pc = runtime_getcallerpc(&b); - ok = false; n = runtime_gcount(); if(n <= b.__count) { @@ -412,12 +413,11 @@ func GoroutineProfile(b Slice) (n int32, ok bool) { G* g = runtime_g(); ok = true; r = (TRecord*)b.__values; - saveg(pc, sp, g, r++); + saveg(g, r++); for(gp = runtime_allg; gp != nil; gp = gp->alllink) { if(gp == g || gp->status == Gdead) continue; - //saveg(gp->sched.pc, gp->sched.sp, gp, r++); - r++; + saveg(gp, r++); } } diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index ade8b9e..2d0044d 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -348,7 +348,7 @@ runtime_mcall(void (*pfn)(G*)) mp = runtime_m(); gp = runtime_g(); - if(gp->dotraceback != nil) + if(gp->traceback != nil) gtraceback(gp); } if (gp == nil || !gp->fromgogo) { @@ -542,11 +542,20 @@ runtime_goroutinetrailer(G *g) } } +struct Traceback +{ + G* gp; + uintptr pcbuf[100]; + int32 c; +}; + void runtime_tracebackothers(G * volatile me) { G * volatile g; + Traceback traceback; + traceback.gp = me; for(g = runtime_allg; g != nil; g = g->alllink) { if(g == me || g->status == Gdead) continue; @@ -567,16 +576,19 @@ runtime_tracebackothers(G * volatile me) continue; } - g->dotraceback = me; + g->traceback = &traceback; #ifdef USING_SPLIT_STACK __splitstack_getcontext(&me->stack_context[0]); #endif getcontext(&me->context); - if(g->dotraceback) { + if(g->traceback != nil) { runtime_gogo(g); } + + runtime_printtrace(traceback.pcbuf, traceback.c); + runtime_goroutinetrailer(g); } } @@ -586,13 +598,13 @@ runtime_tracebackothers(G * volatile me) static void gtraceback(G* gp) { - G* ret; + Traceback* traceback; - runtime_traceback(nil); - runtime_goroutinetrailer(gp); - ret = gp->dotraceback; - gp->dotraceback = nil; - runtime_gogo(ret); + traceback = gp->traceback; + gp->traceback = nil; + traceback->c = runtime_callers(1, traceback->pcbuf, + sizeof traceback->pcbuf / sizeof traceback->pcbuf[0]); + runtime_gogo(traceback->gp); } // Mark this g as m's idle goroutine. diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 8828aa5..5b3283a 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -71,6 +71,8 @@ typedef struct __go_panic_stack Panic; typedef struct __go_func_type FuncType; typedef struct __go_map_type MapType; +typedef struct Traceback Traceback; + /* * per-cpu declaration. */ @@ -151,7 +153,7 @@ struct G // uintptr sigpc; uintptr gopc; // pc of go statement that created this goroutine - G* dotraceback; + Traceback* traceback; ucontext_t context; void* stack_context[10]; @@ -299,6 +301,7 @@ void runtime_goroutineheader(G*); void runtime_goroutinetrailer(G*); void runtime_traceback(); void runtime_tracebackothers(G*); +void runtime_printtrace(uintptr*, int32); String runtime_gostringnocopy(const byte*); void* runtime_mstart(void*); G* runtime_malg(int32, byte**, size_t*); -- cgit v1.1