]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix GC bitmap corruption
authorDmitriy Vyukov <dvyukov@google.com>
Sun, 29 Jun 2014 02:20:46 +0000 (19:20 -0700)
committerDmitriy Vyukov <dvyukov@google.com>
Sun, 29 Jun 2014 02:20:46 +0000 (19:20 -0700)
Fixes #8299.

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

src/pkg/runtime/mgc0.c

index 3eda4f4b9ea369f5935576dddd93abcc6f8ea73c..4ad8f3b08f4b4b83310f20c213e464573de29851 100644 (file)
@@ -2731,7 +2731,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);
@@ -2742,7 +2742,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.