]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: convert a few traceback-related functions from proc.c to traceback.go
authorRuss Cox <rsc@golang.org>
Wed, 3 Sep 2014 15:11:16 +0000 (11:11 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 3 Sep 2014 15:11:16 +0000 (11:11 -0400)
They were in proc.c mainly because there was no portable
traceback source file. As part of converting them to Go,
move to traceback.go.

In order to get access to the PC of _rt0_go,
rename to runtime.rt0_go.

LGTM=r
R=golang-codereviews, r
CC=dvyukov, golang-codereviews, iant, khr
https://golang.org/cl/139110043

33 files changed:
src/cmd/api/goapi.go
src/pkg/runtime/asm_386.s
src/pkg/runtime/asm_amd64.s
src/pkg/runtime/asm_amd64p32.s
src/pkg/runtime/asm_arm.s
src/pkg/runtime/proc.c
src/pkg/runtime/rt0_darwin_386.s
src/pkg/runtime/rt0_darwin_amd64.s
src/pkg/runtime/rt0_dragonfly_386.s
src/pkg/runtime/rt0_dragonfly_amd64.s
src/pkg/runtime/rt0_freebsd_386.s
src/pkg/runtime/rt0_freebsd_amd64.s
src/pkg/runtime/rt0_freebsd_arm.s
src/pkg/runtime/rt0_linux_386.s
src/pkg/runtime/rt0_linux_amd64.s
src/pkg/runtime/rt0_linux_arm.s
src/pkg/runtime/rt0_nacl_386.s
src/pkg/runtime/rt0_nacl_amd64p32.s
src/pkg/runtime/rt0_nacl_arm.s
src/pkg/runtime/rt0_netbsd_386.s
src/pkg/runtime/rt0_netbsd_amd64.s
src/pkg/runtime/rt0_netbsd_arm.s
src/pkg/runtime/rt0_openbsd_386.s
src/pkg/runtime/rt0_openbsd_amd64.s
src/pkg/runtime/rt0_plan9_386.s
src/pkg/runtime/rt0_plan9_amd64.s
src/pkg/runtime/rt0_solaris_amd64.s
src/pkg/runtime/rt0_windows_386.s
src/pkg/runtime/rt0_windows_amd64.s
src/pkg/runtime/runtime.h
src/pkg/runtime/stubs.go
src/pkg/runtime/traceback.go
src/pkg/runtime/traceback_windows.go

index 8dec9e2cc713b5b74f39fee5f36d56ef1ab4fe0a..7f7b389be3215f5c83fefe030cb4b3f731644ba3 100644 (file)
@@ -405,7 +405,17 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
                        " wincallbackcontext struct{};" +
                        " _select struct{}; " +
                        "); " +
-                       "const ( cb_max = 2000 )"
+                       "const (" +
+                       " cb_max = 2000;" +
+                       " _Gidle = 1;" +
+                       " _Grunnable = 2;" +
+                       " _Grunning = 3;" +
+                       " _Gsyscall = 4;" +
+                       " _Gwaiting = 5;" +
+                       " _Gdead = 6;" +
+                       " _Genqueue = 7;" +
+                       " _Gcopystack = 8;" +
+                       ")"
                f, err = parser.ParseFile(fset, filename, src, 0)
                if err != nil {
                        log.Fatalf("incorrect generated file: %s", err)
index 681a1b68198a9fc0bd81e831ba92f165c9054061..e99c114ad759fdacc9bda9fb7089dda3f066c1a1 100644 (file)
@@ -6,7 +6,7 @@
 #include "funcdata.h"
 #include "../../cmd/ld/textflag.h"
 
-TEXT _rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
        // copy arguments forward on an even stack
        MOVL    argc+0(FP), AX
        MOVL    argv+4(FP), BX
index 0121b7d86592f7c32fab49dbfe54d7fc7d65deeb..0933fa92c77f3aa5834349a54a956e67d2b6e69e 100644 (file)
@@ -6,7 +6,7 @@
 #include "funcdata.h"
 #include "../../cmd/ld/textflag.h"
 
-TEXT _rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
        // copy arguments forward on an even stack
        MOVQ    DI, AX          // argc
        MOVQ    SI, BX          // argv
index 03cf9bd4448afacabc8d4999b878c1e70c022b59..4a391033d1cb4505da2ca0b9a6fd8c7174c1422e 100644 (file)
@@ -6,7 +6,7 @@
 #include "funcdata.h"
 #include "../../cmd/ld/textflag.h"
 
-TEXT _rt0_go(SB),NOSPLIT,$0
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
        // copy arguments forward on an even stack
        MOVL    argc+0(FP), AX
        MOVL    argv+4(FP), BX
index 87ea9742460f117623dee5d37a35058d5c22311a..6954bb7c05e7812caac6d4b94d7093a521e036d6 100644 (file)
@@ -7,7 +7,7 @@
 #include "../../cmd/ld/textflag.h"
 
 // using frame size $-4 means do not save LR on stack.
-TEXT _rt0_go(SB),NOSPLIT,$-4
+TEXT runtime·rt0_go(SB),NOSPLIT,$-4
        MOVW    $0xcafebabe, R12
 
        // copy arguments forward on an even stack
index 9229c53a8c18ff0ad60c892c48a75a227f7f67b2..b85baca14d223b6c57f17440f68393c28d2687e0 100644 (file)
@@ -185,8 +185,6 @@ runtime·schedinit(void)
        if(p != nil && !runtime·strcmp(p, (byte*)"0"))
                runtime·copystack = false;
 
-       mstats.enablegc = 1;
-
        if(runtime·buildVersion.str == nil) {
                // Condition should never trigger.  This code just serves
                // to ensure runtime·buildVersion is kept in the resulting binary.
@@ -244,7 +242,10 @@ runtime·main(void)
 
        if(g->m != &runtime·m0)
                runtime·throw("runtime·main not on m0");
+
        runtime·init();
+       mstats.enablegc = 1; // now that runtime is initialized, GC is okay
+
        main·init();
 
        if(g->defer != &d || d.fn != &initDone)
@@ -268,118 +269,12 @@ runtime·main(void)
                *(int32*)runtime·main = 0;
 }
 
-void
-runtime·goroutineheader(G *gp)
-{
-       String status;
-       int64 waitfor;
-       uint32 gpstatus;
-
-       gpstatus = runtime·readgstatus(gp);
-       switch(gpstatus) {
-       case Gidle:
-               status = runtime·gostringnocopy((byte*)"idle");
-               break;
-       case Grunnable:
-               status = runtime·gostringnocopy((byte*)"runnable");
-               break;
-       case Grunning:
-               status = runtime·gostringnocopy((byte*)"running");
-               break;
-       case Gsyscall:
-               status = runtime·gostringnocopy((byte*)"syscall");
-               break;
-       case Gwaiting:
-               if(gp->waitreason.str != nil)
-                       status = gp->waitreason;
-               else
-                       status = runtime·gostringnocopy((byte*)"waiting");
-               break;
-       case Gscan:
-               status = runtime·gostringnocopy((byte*)"scan");
-               break;
-       case Gscanrunnable:
-               status =  runtime·gostringnocopy((byte*)"scanrunnable");
-               break;
-       case Gscanrunning:
-               status = runtime·gostringnocopy((byte*)"scanrunning");
-               break;
-       case Gscansyscall:
-               status = runtime·gostringnocopy((byte*)"scansyscall");
-               break;
-       case Gscanenqueue:
-               status = runtime·gostringnocopy((byte*)"scanenqueue");
-               break;
-       case Gscanwaiting:
-               if(gp->waitreason.str != nil)
-                       status = gp->waitreason;
-               else
-                       status = runtime·gostringnocopy((byte*)"scanwaiting");
-               break;
-       case Gcopystack:
-               status = runtime·gostringnocopy((byte*)"copystack");
-               break;
-       default:
-               status = runtime·gostringnocopy((byte*)"???");
-               break;
-       }
-
-       // approx time the G is blocked, in minutes
-       waitfor = 0;
-       gpstatus = gpstatus&~Gscan; // drop the scan bit
-       if((gpstatus == Gwaiting || gpstatus == Gsyscall) && gp->waitsince != 0)
-               waitfor = (runtime·nanotime() - gp->waitsince) / (60LL*1000*1000*1000);
-
-       runtime·printf("goroutine %D [%S", gp->goid, status);
-       if(waitfor >= 1)
-               runtime·printf(", %D minutes", waitfor);
-       if(gp->lockedm != nil)
-               runtime·printf(", locked to thread");
-       runtime·printf("]:\n");
-}
-
 static void
 dumpgstatus(G* gp)
 {
        runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
 }
 
-void
-runtime·tracebackothers(G *me)
-{
-       G *gp;
-       int32 traceback;
-       uintptr i;
-       uint32 status;
-
-       traceback = runtime·gotraceback(nil);
-       
-       // Show the current goroutine first, if we haven't already.
-       if((gp = g->m->curg) != nil && gp != me) {
-               runtime·printf("\n");
-               runtime·goroutineheader(gp);
-               runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, gp);
-       }
-
-       runtime·lock(&allglock);
-       for(i = 0; i < runtime·allglen; i++) {
-               gp = runtime·allg[i];
-               if(gp == me || gp == g->m->curg || runtime·readgstatus(gp) == Gdead)
-                       continue;
-               if(gp->issystem && traceback < 2)
-                       continue;
-               runtime·printf("\n");
-               runtime·goroutineheader(gp);
-               status = runtime·readgstatus(gp);
-               if((status&~Gscan) == Grunning){
-                       runtime·printf("\tgoroutine running on other thread; stack unavailable\n");
-                       runtime·printcreatedby(gp);
-               } else
-                       runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, gp);
-       }
-       runtime·unlock(&allglock);
-}
-
 static void
 checkmcount(void)
 {
@@ -3373,23 +3268,6 @@ runtime·testSchedLocalQueueSteal(void)
        }
 }
 
-extern void runtime·morestack(void);
-uintptr runtime·externalthreadhandlerp;
-
-// Does f mark the top of a goroutine stack?
-bool
-runtime·topofstack(Func *f)
-{
-       return f->entry == (uintptr)runtime·goexit ||
-               f->entry == (uintptr)runtime·mstart ||
-               f->entry == (uintptr)runtime·mcall ||
-               f->entry == (uintptr)runtime·onM ||
-               f->entry == (uintptr)runtime·morestack ||
-               f->entry == (uintptr)runtime·lessstack ||
-               f->entry == (uintptr)_rt0_go ||
-               (runtime·externalthreadhandlerp != 0 && f->entry == runtime·externalthreadhandlerp);
-}
-
 void
 runtime·setmaxthreads_m(void)
 {
index 4f85250c2d74c555d1809158acf653c0735e5ce3..7fe1df4c902334bc9e3600e31f56909f7199eb91 100644 (file)
@@ -13,4 +13,4 @@ TEXT _rt0_386_darwin(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index 8d2962b03ac124ed50b229a814ae4279d765eab9..ac323c83c2992459103bb3ced55ff604f8ba78fe 100644 (file)
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_darwin(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
index b857f60391aaa5df811cbda3aa4a33d68306f535..9262a0f9e18d6fb5856c6195572d543c82a77c5e 100644 (file)
@@ -13,4 +13,4 @@ TEXT _rt0_386_dragonfly(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index fc7e7459830078a7a5736d2c12e0b0f6bf09c01e..a83b20e228347a4080ee21094542745085d18777 100644 (file)
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_dragonfly(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
index 758f7d2685fb553f41ff19b9ccc2f575a6c5160b..242b67df5e23855205f9ba9c3fd636114487f047 100644 (file)
@@ -13,4 +13,4 @@ TEXT _rt0_386_freebsd(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index 3cf7163b5e01db0dd3ce542a0521978d3b191097..729effbdbabdb6e2cd3e641572fd4084a70d6c51 100644 (file)
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_freebsd(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
index 56219f89995b20fbb6ede5802c40521f348e7608..d50c73c237796b0759eadf01f77b04ab28445911 100644 (file)
@@ -10,9 +10,9 @@ TEXT _rt0_arm_freebsd(SB),NOSPLIT,$-4
        MOVW    (R13), R0       // argc
        MOVW    $4(R13), R1             // argv
        MOVM.DB.W [R0-R1], (R13)
-       B       _rt0_go(SB)
+       B       runtime·rt0_go(SB)
 
 TEXT main(SB),NOSPLIT,$-4
        MOVM.DB.W [R0-R1], (R13)
-       MOVW    $_rt0_go(SB), R4
+       MOVW    $runtime·rt0_go(SB), R4
        B               (R4)
index c6f4159ce34c1ab61b88ea0e506a82fe8484f943..285aeed73c8ae43a5b13b0914506e3917c53e1ea 100644 (file)
@@ -14,7 +14,7 @@ TEXT _rt0_386_linux(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
 
 TEXT _fallback_vdso(SB),NOSPLIT,$0
        INT     $0x80
index a887ced8f01476a428677202f0bc7ff210a39a00..7f8c795481d5ccd38fadf4fd411ea53538ffbcea 100644 (file)
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
index 309fa2f79de1febbe49ec99284c842afed023a3d..21391c7300ad2de9eeeda123c14a37780dfda8a0 100644 (file)
@@ -56,7 +56,7 @@ TEXT _rt0_arm_linux1(SB),NOSPLIT,$-4
        SUB     $4, R13 // fake a stack frame for runtime·setup_auxv
        BL      runtime·setup_auxv(SB)
        ADD     $4, R13
-       B       _rt0_go(SB)
+       B       runtime·rt0_go(SB)
 
 TEXT bad_abi<>(SB),NOSPLIT,$-4
        // give diagnosis and exit
index 8b713548feeffbefa6275ebf83293b6eddb5b2c0..e374bf33599c0bddc9393ec93af9776bce3a3721 100644 (file)
@@ -19,4 +19,4 @@ TEXT _rt0_386_nacl(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index 502d2e2bfc3ea927d5498293351ff34fc2cc4a68..de08618fc8d5dc02a3640af96c7243abd6383215 100644 (file)
@@ -27,4 +27,4 @@ TEXT main(SB),NOSPLIT,$0
        // Uncomment for fake time like on Go Playground.
        //MOVQ  $1257894000000000000, AX
        //MOVQ  AX, runtime·timens(SB)
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index df84d5d02be660383251ff7f6c9873bcc8f782cb..243cb3375d87fdebb8f04e6af3b66ea077a0724c 100644 (file)
@@ -17,4 +17,4 @@ TEXT _rt0_arm_nacl(SB),NOSPLIT,$-4
        B       main(SB)
 
 TEXT main(SB),NOSPLIT,$0
-       B       _rt0_go(SB)
+       B       runtime·rt0_go(SB)
index eb348fcee1fa6def2a0a8f70522686d5f7404ccb..f4cc78a1bc90c67d86790263ee52a03d2e14ee6b 100644 (file)
@@ -13,4 +13,4 @@ TEXT _rt0_386_netbsd(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index c8e3fb18c3ff44240cb74b94bbaa7a073bb5b087..e2288dbaed7c02e56cde6c1f93a765a39866d8cb 100644 (file)
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_netbsd(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
index 36effc3c516916cb8961798e202294d7ce414767..1f649d97c4fa292daef82752a343d4a6e62bf0b1 100644 (file)
@@ -10,4 +10,4 @@ TEXT _rt0_arm_netbsd(SB),NOSPLIT,$-4
        MOVW    (R13), R0       // argc
        MOVW    $4(R13), R1             // argv
        MOVM.DB.W [R0-R1], (R13)
-       B _rt0_go(SB)
+       B runtime·rt0_go(SB)
index 9e80f69be2e120fe53ab51022614e3deec7b2585..35439d0d58068757cadd830452cdf560c8812da5 100644 (file)
@@ -13,4 +13,4 @@ TEXT _rt0_386_openbsd(SB),NOSPLIT,$8
        INT     $3
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
index b1ad403b70035c8f6a4b64981ccb5e7a7de5f76c..a394890f94531f3398a9d2baf706fe74434f6ef5 100644 (file)
@@ -11,5 +11,5 @@ TEXT _rt0_amd64_openbsd(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
index a8ae50841d81abfb1187188d7c31c51496e4c474..4aaabfaa4568cb3c07bd8f47716f1fb240bd98e9 100644 (file)
@@ -14,7 +14,7 @@ TEXT _rt0_386_plan9(SB),NOSPLIT,$12
        MOVL    AX, 0(SP)
        LEAL    inargv+0(FP), AX
        MOVL    AX, 4(SP)
-       CALL    _rt0_go(SB)
+       CALL    runtime·rt0_go(SB)
 
 DATA  runtime·isplan9(SB)/4, $1
 GLOBL runtime·isplan9(SB), $4
index 96d00584dfbddff39322052f4198c0caed332ed4..9f20eef60a6989ca2965411ebbe0d52ae06a9420 100644 (file)
@@ -11,7 +11,7 @@ TEXT _rt0_amd64_plan9(SB),NOSPLIT,$24
        MOVL    $1, _nprivates(SB)
        MOVL    inargc-8(FP), DI
        LEAQ    inargv+0(FP), SI
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
 
 DATA runtime·isplan9(SB)/4, $1
index 4aca991f083d2cd365871a6b877c938e65fd4a77..fd0a79cc9bdad5100ccfa180dfb07da5e698ee5b 100644 (file)
@@ -11,7 +11,7 @@ TEXT _rt0_amd64_solaris(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
 
 DATA runtime·issolaris(SB)/4, $1
index 594e2cd343f533041c60f5882ca1417e21d88068..d4008ad5dc0b8ef7cbaabdb5bf5d12cd0b93f227 100644 (file)
@@ -13,7 +13,7 @@ TEXT _rt0_386_windows(SB),NOSPLIT,$12
        JMP     main(SB)
 
 TEXT main(SB),NOSPLIT,$0
-       JMP     _rt0_go(SB)
+       JMP     runtime·rt0_go(SB)
 
 
 DATA  runtime·iswindows(SB)/4, $1
index 32e18b02baa86e53290bae74c0bdeacd34d3e4b1..0b144717ba37a419272ad0dfb7592ece0d96389c 100644 (file)
@@ -12,7 +12,7 @@ TEXT _rt0_amd64_windows(SB),NOSPLIT,$-8
        JMP     AX
 
 TEXT main(SB),NOSPLIT,$-8
-       MOVQ    $_rt0_go(SB), AX
+       MOVQ    $runtime·rt0_go(SB), AX
        JMP     AX
 
 DATA  runtime·iswindows(SB)/4, $1
index f1b3ee83f35635daddc9069d401b5aaf2b3df23a..3cc6f9a81e41f05693ea0fa3905840b9b924a90e 100644 (file)
@@ -882,7 +882,6 @@ void        runtime·netpolllock(PollDesc*);
 void   runtime·netpollunlock(PollDesc*);
 void   runtime·crash(void);
 void   runtime·parsedebugvars(void);
-void   _rt0_go(void);
 void*  runtime·funcdata(Func*, int32);
 void   runtime·setmaxthreads_m(void);
 G*     runtime·timejump(void);
index cdcf4b36708c8e184aba0a9e3d44a3a0e6fc30c6..86dc47f4ab822fe4b95b6e9fc6a94d6c41169e23 100644 (file)
@@ -138,9 +138,6 @@ func entersyscall()
 func entersyscallblock()
 func exitsyscall()
 
-func goroutineheader(gp *g)
-func tracebackothers(gp *g)
-
 func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
 func gogo(buf *gobuf)
 func gosave(buf *gobuf)
@@ -260,4 +257,3 @@ var newproc, deferproc, lessstack struct{} // C/assembly functions
 func funcspdelta(*_func, uintptr) int32 // symtab.c
 func funcarglen(*_func, uintptr) int32  // symtab.c
 const _ArgsSizeUnknown = -0x80000000    // funcdata.h
-func topofstack(*_func) bool            // proc.c
index c6a6c056c192e10b1294a0e724fe1667cab725d3..26d0f5fc92caab0b5882e728dbf51e4695aebd72 100644 (file)
@@ -32,12 +32,7 @@ const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386"
 
 // jmpdeferPC is the PC at the beginning of the jmpdefer assembly function.
 // The traceback needs to recognize it on link register architectures.
-var jmpdeferPC uintptr
-
-func init() {
-       f := jmpdefer
-       jmpdeferPC = **(**uintptr)(unsafe.Pointer(&f))
-}
+var jmpdeferPC = funcPC(jmpdefer)
 
 // System-specific hook. See traceback_windows.go
 var systraceback func(*_func, *stkframe, *g, bool, func(*stkframe, unsafe.Pointer) bool, unsafe.Pointer) (changed, aborted bool)
@@ -502,3 +497,117 @@ func callers(skip int, pcbuf *uintptr, m int) int {
 func gcallers(gp *g, skip int, pcbuf *uintptr, m int) int {
        return gentraceback(^uintptr(0), ^uintptr(0), 0, gp, skip, pcbuf, m, nil, nil, false)
 }
+
+var gStatusStrings = [...]string{
+       _Gidle:      "idle",
+       _Grunnable:  "runnable",
+       _Grunning:   "running",
+       _Gsyscall:   "syscall",
+       _Gwaiting:   "waiting",
+       _Gdead:      "dead",
+       _Genqueue:   "enqueue",
+       _Gcopystack: "copystack",
+}
+
+var gScanStatusStrings = [...]string{
+       0:          "scan",
+       _Grunnable: "scanrunnable",
+       _Grunning:  "scanrunning",
+       _Gsyscall:  "scansyscall",
+       _Gwaiting:  "scanwaiting",
+       _Gdead:     "scandead",
+       _Genqueue:  "scanenqueue",
+}
+
+func goroutineheader(gp *g) {
+       gpstatus := readgstatus(gp)
+
+       // Basic string status
+       var status string
+       if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) {
+               status = gStatusStrings[gpstatus]
+       } else if gpstatus&_Gscan != 0 && 0 <= gpstatus&^_Gscan && gpstatus&^_Gscan < uint32(len(gStatusStrings)) {
+               status = gStatusStrings[gpstatus&^_Gscan]
+       } else {
+               status = "???"
+       }
+
+       // Override.
+       if (gpstatus == _Gwaiting || gpstatus == _Gscanwaiting) && gp.waitreason != "" {
+               status = gp.waitreason
+       }
+
+       // approx time the G is blocked, in minutes
+       var waitfor int64
+       gpstatus &^= _Gscan // drop the scan bit
+       if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 {
+               waitfor = (nanotime() - gp.waitsince) / 60e9
+       }
+       print("goroutine ", gp.goid, " [", status)
+       if waitfor >= 1 {
+               print(", ", waitfor, " minutes")
+       }
+       if gp.lockedm != nil {
+               print(", locked to thread")
+       }
+       print("]:\n")
+}
+
+func tracebackothers(me *g) {
+       level := gotraceback(nil)
+
+       // Show the current goroutine first, if we haven't already.
+       g := getg()
+       gp := g.m.curg
+       if gp != nil && gp != me {
+               print("\n")
+               goroutineheader(gp)
+               traceback(^uintptr(0), ^uintptr(0), 0, gp)
+       }
+
+       lock(&allglock)
+       for _, gp := range allgs {
+               if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || gp.issystem && level < 2 {
+                       continue
+               }
+               print("\n")
+               goroutineheader(gp)
+               if readgstatus(gp)&^_Gscan == _Grunning {
+                       print("\tgoroutine running on other thread; stack unavailable\n")
+                       printcreatedby(gp)
+               } else {
+                       traceback(^uintptr(0), ^uintptr(0), 0, gp)
+               }
+       }
+       unlock(&allglock)
+}
+
+func goexit()
+func mstart()
+func morestack()
+func rt0_go()
+
+var (
+       goexitPC    = funcPC(goexit)
+       mstartPC    = funcPC(mstart)
+       mcallPC     = funcPC(mcall)
+       onMPC       = funcPC(onM)
+       morestackPC = funcPC(morestack)
+       lessstackPC = funcPC(lessstack)
+       rt0_goPC    = funcPC(rt0_go)
+
+       externalthreadhandlerp uintptr // initialized elsewhere
+)
+
+// Does f mark the top of a goroutine stack?
+func topofstack(f *_func) bool {
+       pc := f.entry
+       return pc == goexitPC ||
+               pc == mstartPC ||
+               pc == mcallPC ||
+               pc == onMPC ||
+               pc == morestackPC ||
+               pc == lessstackPC ||
+               pc == rt0_goPC ||
+               externalthreadhandlerp != 0 && pc == externalthreadhandlerp
+}
index 206f93c46ea941dc753662fb04cd00c7c7888bee..892bed04caceabd451d88af007bad7abd88cca25 100644 (file)
@@ -13,8 +13,7 @@ var sigtrampPC uintptr
 var sigtramp struct{} // assembly function
 
 func init() {
-       f := sigtramp
-       sigtrampPC = **(**uintptr)(unsafe.Pointer(&f))
+       sigtrampPC = funcPC(sigtramp)
        systraceback = traceback_windows
 }