]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.3] runtime: fix GC bitmap corruption
authorAndrew Gerrand <adg@golang.org>
Wed, 13 Aug 2014 03:20:01 +0000 (13:20 +1000)
committerAndrew Gerrand <adg@golang.org>
Wed, 13 Aug 2014 03:20:01 +0000 (13:20 +1000)
««« CL 103640044 / d2f256096d8d
runtime: fix GC bitmap corruption
Fixes #8299.

R=golang-codereviews
CC=golang-codereviews, khr, rsc
https://golang.org/cl/103640044
»»»

TBR=r, rsc
CC=golang-codereviews
https://golang.org/cl/125150044

src/pkg/runtime/mgc0.c

index 392da535b1509b6b850bfc32571cf5eeeff6b1b8..9b23c53c2135e887a07a654121bbd924e0f0404b 100644 (file)
@@ -2760,7 +2760,7 @@ runtime·markscan(void *v)
 void
 runtime·markfreed(void *v)
 {
-       uintptr *b, off, shift;
+       uintptr *b, off, shift, xbits;
 
        if(0)
                runtime·printf("markfreed %p\n", v);
@@ -2771,7 +2771,18 @@ runtime·markfreed(void *v)
        off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;  // word offset
        b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
        shift = off % wordsPerBitmapWord;
-       *b = (*b & ~(bitMask<<shift)) | (bitAllocated<<shift);
+       if(!g->m->gcing || work.nproc == 1) {
+               // During normal operation (not GC), the span bitmap is not updated concurrently,
+               // because either the span is cached or accesses are protected with MCentral lock.
+               *b = (*b & ~(bitMask<<shift)) | (bitAllocated<<shift);
+       } else {
+               // During GC other threads concurrently mark heap.
+               for(;;) {
+                       xbits = *b;
+                       if(runtime·casp((void**)b, (void*)xbits, (void*)((xbits & ~(bitMask<<shift)) | (bitAllocated<<shift))))
+                               break;
+               }
+       }
 }
 
 // check that the block at v of size n is marked freed.