]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix GC bitmap corruption
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 16 Aug 2011 20:53:02 +0000 (16:53 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 16 Aug 2011 20:53:02 +0000 (16:53 -0400)
The corruption can occur when GOMAXPROCS
is changed from >1 to 1, since GOMAXPROCS=1
does not imply there is only 1 goroutine running,
other goroutines can still be not parked after
the change.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4873050

src/pkg/runtime/mgc0.c
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h

index 6325aadc67273ded5dc618554096c82bd57c3ac4..78ea2aa2b9d77c7618255583fc0e71056f703bf0 100644 (file)
@@ -737,11 +737,11 @@ runtime·markallocated(void *v, uintptr n, bool noptr)
                bits = (obits & ~(bitMask<<shift)) | (bitAllocated<<shift);
                if(noptr)
                        bits |= bitNoPointers<<shift;
-               if(runtime·gomaxprocs == 1) {
+               if(runtime·singleproc) {
                        *b = bits;
                        break;
                } else {
-                       // gomaxprocs > 1: use atomic op
+                       // more than one goroutine is potentially running: use atomic op
                        if(runtime·casp((void**)b, (void*)obits, (void*)bits))
                                break;
                }
@@ -767,11 +767,11 @@ runtime·markfreed(void *v, uintptr n)
        for(;;) {
                obits = *b;
                bits = (obits & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
-               if(runtime·gomaxprocs == 1) {
+               if(runtime·singleproc) {
                        *b = bits;
                        break;
                } else {
-                       // gomaxprocs > 1: use atomic op
+                       // more than one goroutine is potentially running: use atomic op
                        if(runtime·casp((void**)b, (void*)obits, (void*)bits))
                                break;
                }
@@ -878,11 +878,11 @@ runtime·setblockspecial(void *v)
        for(;;) {
                obits = *b;
                bits = obits | (bitSpecial<<shift);
-               if(runtime·gomaxprocs == 1) {
+               if(runtime·singleproc) {
                        *b = bits;
                        break;
                } else {
-                       // gomaxprocs > 1: use atomic op
+                       // more than one goroutine is potentially running: use atomic op
                        if(runtime·casp((void**)b, (void*)obits, (void*)bits))
                                break;
                }
index 7a81591007fe868952836e80ed16e3429e3191f4..5f396b49f3690de6d6552b99597f2297ab007ba4 100644 (file)
@@ -126,6 +126,7 @@ enum {
 
 Sched runtime·sched;
 int32 runtime·gomaxprocs;
+bool runtime·singleproc;
 
 // An m that is waiting for notewakeup(&m->havenextg).  This may be
 // only be accessed while the scheduler lock is held.  This is used to
@@ -199,6 +200,7 @@ runtime·schedinit(void)
                runtime·gomaxprocs = n;
        }
        setmcpumax(runtime·gomaxprocs);
+       runtime·singleproc = runtime·gomaxprocs == 1;
        runtime·sched.predawn = 1;
 
        m->nomemprof--;
@@ -585,6 +587,7 @@ runtime·stoptheworld(void)
                runtime·notesleep(&runtime·sched.stopped);
                schedlock();
        }
+       runtime·singleproc = runtime·gomaxprocs == 1;
        schedunlock();
 }
 
@@ -1416,6 +1419,8 @@ runtime·gomaxprocsfunc(int32 n)
        if(n > maxgomaxprocs)
                n = maxgomaxprocs;
        runtime·gomaxprocs = n;
+       if(runtime·gomaxprocs > 1)
+               runtime·singleproc = false;
        if(runtime·gcwaiting != 0) {
                if(atomic_mcpumax(runtime·sched.atomic) != 1)
                        runtime·throw("invalid mcpumax during gc");
index 00be565ce02e61512b86d56a03e747dbf589e029..3c503e430b590f69e78e5f380b70c9855888def2 100644 (file)
@@ -383,6 +383,7 @@ extern      String  runtime·emptystring;
 G*     runtime·allg;
 M*     runtime·allm;
 extern int32   runtime·gomaxprocs;
+extern bool    runtime·singleproc;
 extern uint32  runtime·panicking;
 extern int32   runtime·gcwaiting;             // gc is waiting to run
 int8*  runtime·goos;