]> Cypherpunks repositories - gostls13.git/commitdiff
undo CL 7301062 / 9742f722b558
authorRuss Cox <rsc@golang.org>
Tue, 5 Mar 2013 20:36:40 +0000 (15:36 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 5 Mar 2013 20:36:40 +0000 (15:36 -0500)
broke arm garbage collector

traceback_arm fails with a missing pc. It needs CL 7494043.
But that only makes the build break later, this time with
"invalid freelist". Roll back until it can be fixed correctly.

««« original CL description
runtime: restrict stack root scan to locals and arguments

R=rsc
CC=golang-dev
https://golang.org/cl/7301062
»»»

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/7493044

src/pkg/runtime/mgc0.c
src/pkg/runtime/mprof.goc
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h
src/pkg/runtime/sigqueue.goc
src/pkg/runtime/traceback_arm.c
src/pkg/runtime/traceback_x86.c

index f275a53d447c9a28211defc8d8704b59e2dea348..010f9cd9615795497c5061b152c9fb37a6475d2a 100644 (file)
@@ -1299,53 +1299,52 @@ addroot(Obj obj)
        work.nroot++;
 }
 
-static void
-addframeroots(Func *f, byte*, byte *sp, void*)
-{
-       if (f->frame > sizeof(uintptr))
-               addroot((Obj){sp, f->frame - sizeof(uintptr), 0});
-       if (f->args > 0)
-               addroot((Obj){sp + f->frame, f->args, 0});
-}
-
 static void
 addstackroots(G *gp)
 {
        M *mp;
-       Func *f;
-       byte *sp, *pc;
+       int32 n;
+       Stktop *stk;
+       byte *sp, *guard;
+
+       stk = (Stktop*)gp->stackbase;
+       guard = (byte*)gp->stackguard;
 
        if(gp == g) {
                // Scanning our own stack: start at &gp.
                sp = (byte*)&gp;
-               pc = runtime·getcallerpc(&gp);
        } else if((mp = gp->m) != nil && mp->helpgc) {
                // gchelper's stack is in active use and has no interesting pointers.
                return;
-       } else if(gp->gcstack != (uintptr)nil) {
-               // Scanning another goroutine that is about to enter or might
-               // have just exited a system call. It may be executing code such
-               // as schedlock and may have needed to start a new stack segment.
-               // Use the stack segment and stack pointer at the time of
-               // the system call instead, since that won't change underfoot.
-               sp = (byte*)gp->gcsp;
-               pc = gp->gcpc;
        } else {
                // Scanning another goroutine's stack.
                // The goroutine is usually asleep (the world is stopped).
                sp = (byte*)gp->sched.sp;
-               pc = gp->sched.pc;
-               if (pc == (byte*)runtime·goexit && gp->fnstart != nil) {
-                       // The goroutine has not started.  Its incoming
-                       // arguments are at the top of the stack and must
-                       // be scanned.  No other data on the stack.
-                       f = runtime·findfunc((uintptr)gp->fnstart->fn);
-                       if (f->args > 0)
-                               addroot((Obj){sp, f->args, 0});
-                       return;
+
+               // The exception is that if the goroutine is about to enter or might
+               // have just exited a system call, it may be executing code such
+               // as schedlock and may have needed to start a new stack segment.
+               // Use the stack segment and stack pointer at the time of
+               // the system call instead, since that won't change underfoot.
+               if(gp->gcstack != (uintptr)nil) {
+                       stk = (Stktop*)gp->gcstack;
+                       sp = (byte*)gp->gcsp;
+                       guard = (byte*)gp->gcguard;
                }
        }
-       runtime·gentraceback(pc, sp, nil, gp, 0, nil, 0x7fffffff, addframeroots, nil);
+
+       n = 0;
+       while(stk) {
+               if(sp < guard-StackGuard || (byte*)stk < sp) {
+                       runtime·printf("scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
+                       runtime·throw("scanstack");
+               }
+               addroot((Obj){sp, (byte*)stk - sp, 0});
+               sp = (byte*)stk->gobuf.sp;
+               guard = stk->stackguard;
+               stk = (Stktop*)stk->stackbase;
+               n++;
+       }
 }
 
 static void
index 707e505ba74041ec16de6e5d44c96bc453a3e924..ebc1e3e6616e03fe4b7c873608178833a8c681e9 100644 (file)
@@ -511,7 +511,7 @@ saveg(byte *pc, byte *sp, G *gp, TRecord *r)
 {
        int32 n;
        
-       n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk), nil, nil);
+       n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk));
        if(n < nelem(r->stk))
                r->stk[n] = 0;
 }
index 2a47ce1e1f49384675b9d1c2de7f64465107b065..4ce0a718cd776f631ceee969eab41e618887067b 100644 (file)
@@ -1710,7 +1710,7 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
                runtime·unlock(&prof);
                return;
        }
-       n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil);
+       n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf));
        if(n > 0)
                prof.fn(prof.pcbuf, n);
        runtime·unlock(&prof);
index 8ed18432d8478f741bdfe400a22c9ce28ee11a93..e44064f1ae8fecaca31c4e9317bfd7a992dbde25 100644 (file)
@@ -749,7 +749,7 @@ void        runtime·exitsyscall(void);
 G*     runtime·newproc1(FuncVal*, byte*, int32, int32, void*);
 bool   runtime·sigsend(int32 sig);
 int32  runtime·callers(int32, uintptr*, int32);
-int32  runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32,  void (*fn)(Func*, byte*, byte*, void*), void *arg);
+int32  runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32);
 int64  runtime·nanotime(void);
 void   runtime·dopanic(int32);
 void   runtime·startpanic(void);
index 226ea795b05c8456ff833b9fb56d20690f9e3860..ab5f312e420134640e3d2d52c5d04d3cc881c8df 100644 (file)
@@ -83,8 +83,7 @@ runtime·sigsend(int32 s)
 func signal_recv() (m uint32) {
        static uint32 recv[nelem(sig.mask)];
        uint32 i, old, new;
-
-       g->issystem = true;
+       
        for(;;) {
                // Serve from local copy if there are bits left.
                for(i=0; i<NSIG; i++) {
index 1b4176803906aa3bb5a8bbf1091d4f292adf0b3a..dd85cc02c4a43c0e095cfdb9be1b1b6192b42c05 100644 (file)
@@ -17,9 +17,9 @@ void _divu(void);
 void _modu(void);
 
 int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*fn)(Func*, byte*, byte*, void*), void *arg)
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max)
 {
-       int32 i, n;
+       int32 i, n, iter;
        uintptr pc, lr, tracepc, x;
        byte *fp;
        bool waspanic;
@@ -46,7 +46,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
 
        n = 0;
        stk = (Stktop*)gp->stackbase;
-       while(n < max) {
+       for(iter = 0; iter < 100 && n < max; iter++) {  // iter avoids looping forever
                // Typically:
                //      pc is the PC of the running function.
                //      sp is the stack pointer at that program counter.
@@ -60,17 +60,14 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        sp = (byte*)stk->gobuf.sp;
                        lr = 0;
                        fp = nil;
-                       if(pcbuf == nil && fn == nil && runtime·showframe(nil, gp == m->curg))
+                       if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
                                runtime·printf("----- stack segment boundary -----\n");
                        stk = (Stktop*)stk->stackbase;
                        continue;
                }
                
-               if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
-                       if(fn != nil)
-                               runtime·throw("unknown pc");
+               if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil)
                        break;
-               }
                
                // Found an actual function.
                if(lr == 0)
@@ -85,8 +82,6 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        skip--;
                else if(pcbuf != nil)
                        pcbuf[n++] = pc;
-               else if(fn != nil)
-                       (*fn)(f, (byte*)pc, sp, arg);
                else {
                        if(runtime·showframe(f, gp == m->curg)) {
                                // Print during crash.
@@ -118,7 +113,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                
                waspanic = f->entry == (uintptr)runtime·sigpanic;
 
-               if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·newstack && gp == m->g0) {
+               if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && gp == m->g0) {
                        runtime·printf("----- newstack called from goroutine %D -----\n", m->curg->goid);
                        pc = (uintptr)m->morepc;
                        sp = (byte*)m->moreargp - sizeof(void*);
@@ -129,7 +124,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        continue;
                }
                
-               if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
+               if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
                        runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid);
                        gp = m->curg;
                        stk = (Stktop*)gp->stackbase;
@@ -140,10 +135,6 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        continue;
                }       
                
-               // Do not unwind past the bottom of the stack.
-               if(pc == (uintptr)runtime·goexit)
-                       break;
-
                // Unwind to next frame.
                pc = lr;
                lr = 0;
@@ -171,7 +162,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                }
        }
        
-       if(pcbuf == nil && fn == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+       if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
                        && runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
                runtime·printf("created by %S\n", f->name);
                tracepc = pc;   // back up to CALL instruction for funcline.
@@ -195,7 +186,7 @@ runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp)
                sp = (byte*)gp->sched.sp;
                lr = nil;
        }
-       runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100, nil, nil);
+       runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100);
 }
 
 // func caller(n int) (pc uintptr, file string, line int, ok bool)
@@ -207,5 +198,5 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
        sp = runtime·getcallersp(&skip);
        pc = runtime·getcallerpc(&skip);
 
-       return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil);
+       return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m);
 }
index ce52df870251a336b2e84f7e81f6db3fbb029ac1..72603ae8ee02b5efcc701a32bf70fa539ecb8328 100644 (file)
@@ -17,14 +17,14 @@ void runtime·sigpanic(void);
 // This code is also used for the 386 tracebacks.
 // Use uintptr for an appropriate word-sized integer.
 
-// Generic traceback.  Handles runtime stack prints (pcbuf == nil),
-// the runtime.Callers function (pcbuf != nil), as well as the garbage
-// collector (fn != nil).  A little clunky to merge the two but avoids
-// duplicating the code and all its subtlety.
+// Generic traceback.  Handles runtime stack prints (pcbuf == nil)
+// as well as the runtime.Callers function (pcbuf != nil).
+// A little clunky to merge the two but avoids duplicating
+// the code and all its subtlety.
 int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*fn)(Func*, byte*, byte*, void*), void *arg)
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max)
 {
-       int32 i, n, sawnewstack;
+       int32 i, n, iter, sawnewstack;
        uintptr pc, lr, tracepc;
        byte *fp;
        Stktop *stk;
@@ -54,7 +54,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
        n = 0;
        sawnewstack = 0;
        stk = (Stktop*)gp->stackbase;
-       while(n < max) {
+       for(iter = 0; iter < 100 && n < max; iter++) {  // iter avoids looping forever
                // Typically:
                //      pc is the PC of the running function.
                //      sp is the stack pointer at that program counter.
@@ -68,16 +68,13 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        sp = (byte*)stk->gobuf.sp;
                        lr = 0;
                        fp = nil;
-                       if(pcbuf == nil && fn == nil && runtime·showframe(nil, gp == m->curg))
+                       if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
                                runtime·printf("----- stack segment boundary -----\n");
                        stk = (Stktop*)stk->stackbase;
                        continue;
                }
-               if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
-                       if(fn != nil)
-                               runtime·throw("unknown pc");
+               if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil)
                        break;
-               }
 
                // Found an actual function.
                if(fp == nil) {
@@ -94,8 +91,6 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        skip--;
                else if(pcbuf != nil)
                        pcbuf[n++] = pc;
-               else if(fn != nil)
-                       (*fn)(f, (byte*)pc, sp, arg);
                else {
                        if(runtime·showframe(f, gp == m->curg)) {
                                // Print during crash.
@@ -134,7 +129,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                if(f->entry == (uintptr)runtime·newstack)
                        sawnewstack = 1;
 
-               if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·morestack && gp == m->g0 && sawnewstack) {
+               if(pcbuf == nil && f->entry == (uintptr)runtime·morestack && gp == m->g0 && sawnewstack) {
                        // The fact that we saw newstack means that morestack
                        // has managed to record its information in m, so we can
                        // use it to keep unwinding the stack.
@@ -149,7 +144,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        continue;
                }
 
-               if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
+               if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
                        // Lessstack is running on scheduler stack.  Switch to original goroutine.
                        runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid);
                        gp = m->curg;
@@ -161,10 +156,6 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
                        continue;
                }
 
-               // Do not unwind past the bottom of the stack.
-               if(pc == (uintptr)runtime·goexit)
-                       break;
-
                // Unwind to next frame.
                pc = lr;
                lr = 0;
@@ -173,7 +164,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
        }
        
        // Show what created goroutine, except main goroutine (goid 1).
-       if(pcbuf == nil && fn == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+       if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
                        && runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
                runtime·printf("created by %S\n", f->name);
                tracepc = pc;   // back up to CALL instruction for funcline.
@@ -196,7 +187,7 @@ runtime·traceback(byte *pc0, byte *sp, byte*, G *gp)
                pc0 = gp->sched.pc;
                sp = (byte*)gp->sched.sp;
        }
-       runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100, nil, nil);
+       runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100);
 }
 
 int32
@@ -208,5 +199,5 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
        sp = (byte*)&skip;
        pc = runtime·getcallerpc(&skip);
 
-       return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m, nil, nil);
+       return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m);
 }