runtime: Make runtime.Stack actually work.

From-SVN: r187854
This commit is contained in:
Ian Lance Taylor 2012-05-24 21:07:18 +00:00
parent 27c53c0cce
commit bac564c53e
4 changed files with 62 additions and 67 deletions

View File

@ -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)
{
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);
}
return _URC_NO_REASON;
}
/* Print a stack trace for the current goroutine. */
void
runtime_traceback ()
{
int c;
uintptr pcbuf[100];
int32 c;
c = 0;
_Unwind_Backtrace (traceback, &c);
c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]);
runtime_printtrace (pcbuf, c);
}
void
runtime_printtrace (uintptr *pcbuf, int32 c)
{
int32 i;
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);
}
}
}

View File

@ -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++);
}
}

View File

@ -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.

View File

@ -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*);