mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-03 08:44:23 +08:00
runtime: Make runtime.Stack actually work.
From-SVN: r187854
This commit is contained in:
parent
27c53c0cce
commit
bac564c53e
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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++);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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*);
|
||||
|
Loading…
Reference in New Issue
Block a user