mirror of git://gcc.gnu.org/git/gcc.git
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 "config.h"
|
||||||
|
|
||||||
#include "unwind.h"
|
|
||||||
|
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "go-string.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. */
|
/* Print a stack trace for the current goroutine. */
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime_traceback ()
|
runtime_traceback ()
|
||||||
{
|
{
|
||||||
int c;
|
uintptr pcbuf[100];
|
||||||
|
int32 c;
|
||||||
|
|
||||||
c = 0;
|
c = runtime_callers (1, pcbuf, sizeof pcbuf / sizeof pcbuf[0]);
|
||||||
_Unwind_Backtrace (traceback, &c);
|
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) {
|
func Stack(b Slice, all bool) (n int32) {
|
||||||
byte *pc, *sp;
|
byte *pc, *sp;
|
||||||
|
bool enablegc;
|
||||||
|
|
||||||
sp = runtime_getcallersp(&b);
|
sp = runtime_getcallersp(&b);
|
||||||
pc = runtime_getcallerpc(&b);
|
pc = runtime_getcallerpc(&b);
|
||||||
|
|
@ -351,6 +352,8 @@ func Stack(b Slice, all bool) (n int32) {
|
||||||
runtime_semacquire(&runtime_worldsema);
|
runtime_semacquire(&runtime_worldsema);
|
||||||
runtime_m()->gcing = 1;
|
runtime_m()->gcing = 1;
|
||||||
runtime_stoptheworld();
|
runtime_stoptheworld();
|
||||||
|
enablegc = mstats.enablegc;
|
||||||
|
mstats.enablegc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(b.__count == 0)
|
if(b.__count == 0)
|
||||||
|
|
@ -373,33 +376,31 @@ func Stack(b Slice, all bool) (n int32) {
|
||||||
|
|
||||||
if(all) {
|
if(all) {
|
||||||
runtime_m()->gcing = 0;
|
runtime_m()->gcing = 0;
|
||||||
|
mstats.enablegc = enablegc;
|
||||||
runtime_semrelease(&runtime_worldsema);
|
runtime_semrelease(&runtime_worldsema);
|
||||||
runtime_starttheworld(false);
|
runtime_starttheworld(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
saveg(byte *pc, byte *sp, G *g, TRecord *r)
|
saveg(G *g, TRecord *r)
|
||||||
{
|
{
|
||||||
int32 n;
|
int32 n;
|
||||||
|
|
||||||
USED(pc);
|
if(g == runtime_g())
|
||||||
USED(sp);
|
n = runtime_callers(0, r->stk, nelem(r->stk));
|
||||||
USED(g);
|
else {
|
||||||
// n = runtime_gentraceback(pc, sp, 0, g, 0, r->stk, nelem(r->stk));
|
// FIXME: Not implemented.
|
||||||
n = 0;
|
n = 0;
|
||||||
|
}
|
||||||
if((size_t)n < nelem(r->stk))
|
if((size_t)n < nelem(r->stk))
|
||||||
r->stk[n] = 0;
|
r->stk[n] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
func GoroutineProfile(b Slice) (n int32, ok bool) {
|
func GoroutineProfile(b Slice) (n int32, ok bool) {
|
||||||
byte *pc, *sp;
|
|
||||||
TRecord *r;
|
TRecord *r;
|
||||||
G *gp;
|
G *gp;
|
||||||
|
|
||||||
sp = runtime_getcallersp(&b);
|
|
||||||
pc = runtime_getcallerpc(&b);
|
|
||||||
|
|
||||||
ok = false;
|
ok = false;
|
||||||
n = runtime_gcount();
|
n = runtime_gcount();
|
||||||
if(n <= b.__count) {
|
if(n <= b.__count) {
|
||||||
|
|
@ -412,12 +413,11 @@ func GoroutineProfile(b Slice) (n int32, ok bool) {
|
||||||
G* g = runtime_g();
|
G* g = runtime_g();
|
||||||
ok = true;
|
ok = true;
|
||||||
r = (TRecord*)b.__values;
|
r = (TRecord*)b.__values;
|
||||||
saveg(pc, sp, g, r++);
|
saveg(g, r++);
|
||||||
for(gp = runtime_allg; gp != nil; gp = gp->alllink) {
|
for(gp = runtime_allg; gp != nil; gp = gp->alllink) {
|
||||||
if(gp == g || gp->status == Gdead)
|
if(gp == g || gp->status == Gdead)
|
||||||
continue;
|
continue;
|
||||||
//saveg(gp->sched.pc, gp->sched.sp, gp, r++);
|
saveg(gp, r++);
|
||||||
r++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ runtime_mcall(void (*pfn)(G*))
|
||||||
mp = runtime_m();
|
mp = runtime_m();
|
||||||
gp = runtime_g();
|
gp = runtime_g();
|
||||||
|
|
||||||
if(gp->dotraceback != nil)
|
if(gp->traceback != nil)
|
||||||
gtraceback(gp);
|
gtraceback(gp);
|
||||||
}
|
}
|
||||||
if (gp == nil || !gp->fromgogo) {
|
if (gp == nil || !gp->fromgogo) {
|
||||||
|
|
@ -542,11 +542,20 @@ runtime_goroutinetrailer(G *g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Traceback
|
||||||
|
{
|
||||||
|
G* gp;
|
||||||
|
uintptr pcbuf[100];
|
||||||
|
int32 c;
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime_tracebackothers(G * volatile me)
|
runtime_tracebackothers(G * volatile me)
|
||||||
{
|
{
|
||||||
G * volatile g;
|
G * volatile g;
|
||||||
|
Traceback traceback;
|
||||||
|
|
||||||
|
traceback.gp = me;
|
||||||
for(g = runtime_allg; g != nil; g = g->alllink) {
|
for(g = runtime_allg; g != nil; g = g->alllink) {
|
||||||
if(g == me || g->status == Gdead)
|
if(g == me || g->status == Gdead)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -567,16 +576,19 @@ runtime_tracebackothers(G * volatile me)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->dotraceback = me;
|
g->traceback = &traceback;
|
||||||
|
|
||||||
#ifdef USING_SPLIT_STACK
|
#ifdef USING_SPLIT_STACK
|
||||||
__splitstack_getcontext(&me->stack_context[0]);
|
__splitstack_getcontext(&me->stack_context[0]);
|
||||||
#endif
|
#endif
|
||||||
getcontext(&me->context);
|
getcontext(&me->context);
|
||||||
|
|
||||||
if(g->dotraceback) {
|
if(g->traceback != nil) {
|
||||||
runtime_gogo(g);
|
runtime_gogo(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runtime_printtrace(traceback.pcbuf, traceback.c);
|
||||||
|
runtime_goroutinetrailer(g);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -586,13 +598,13 @@ runtime_tracebackothers(G * volatile me)
|
||||||
static void
|
static void
|
||||||
gtraceback(G* gp)
|
gtraceback(G* gp)
|
||||||
{
|
{
|
||||||
G* ret;
|
Traceback* traceback;
|
||||||
|
|
||||||
runtime_traceback(nil);
|
traceback = gp->traceback;
|
||||||
runtime_goroutinetrailer(gp);
|
gp->traceback = nil;
|
||||||
ret = gp->dotraceback;
|
traceback->c = runtime_callers(1, traceback->pcbuf,
|
||||||
gp->dotraceback = nil;
|
sizeof traceback->pcbuf / sizeof traceback->pcbuf[0]);
|
||||||
runtime_gogo(ret);
|
runtime_gogo(traceback->gp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this g as m's idle goroutine.
|
// 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_func_type FuncType;
|
||||||
typedef struct __go_map_type MapType;
|
typedef struct __go_map_type MapType;
|
||||||
|
|
||||||
|
typedef struct Traceback Traceback;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* per-cpu declaration.
|
* per-cpu declaration.
|
||||||
*/
|
*/
|
||||||
|
|
@ -151,7 +153,7 @@ struct G
|
||||||
// uintptr sigpc;
|
// uintptr sigpc;
|
||||||
uintptr gopc; // pc of go statement that created this goroutine
|
uintptr gopc; // pc of go statement that created this goroutine
|
||||||
|
|
||||||
G* dotraceback;
|
Traceback* traceback;
|
||||||
|
|
||||||
ucontext_t context;
|
ucontext_t context;
|
||||||
void* stack_context[10];
|
void* stack_context[10];
|
||||||
|
|
@ -299,6 +301,7 @@ void runtime_goroutineheader(G*);
|
||||||
void runtime_goroutinetrailer(G*);
|
void runtime_goroutinetrailer(G*);
|
||||||
void runtime_traceback();
|
void runtime_traceback();
|
||||||
void runtime_tracebackothers(G*);
|
void runtime_tracebackothers(G*);
|
||||||
|
void runtime_printtrace(uintptr*, int32);
|
||||||
String runtime_gostringnocopy(const byte*);
|
String runtime_gostringnocopy(const byte*);
|
||||||
void* runtime_mstart(void*);
|
void* runtime_mstart(void*);
|
||||||
G* runtime_malg(int32, byte**, size_t*);
|
G* runtime_malg(int32, byte**, size_t*);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue