===================================================================
@@ -343,6 +343,7 @@ func ThreadCreateProfile(p Slice) (n int
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,
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++);
}
}
===================================================================
@@ -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*);
===================================================================
@@ -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.
===================================================================
@@ -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;
+/* Print a stack trace for the current goroutine. */
- if (runtime_showframe (fn.__data))
- {
- runtime_printf ("%s\n", fn.__data);
- runtime_printf ("\t%s:%d\n", file.__data, line);
- }
+void
+runtime_traceback ()
+{
+ 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);
+ }
+ }
}