OSDN Git Service

runtime: Make runtime.Stack actually work.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 May 2012 21:07:30 +0000 (21:07 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 May 2012 21:07:30 +0000 (21:07 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@187855 138bc75d-0d04-0410-961f-82ee72b054a4

libgo/runtime/go-traceback.c
libgo/runtime/mprof.goc
libgo/runtime/proc.c
libgo/runtime/runtime.h

index 2ff2ce3..4e99ca7 100644 (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)
+/* 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);
+       }
+    }
 }
index a8bee20..875abe3 100644 (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++);
                        }
                }
        
index ade8b9e..2d0044d 100644 (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.
index 8828aa5..5b3283a 100644 (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*);