diff options
author | Andrew Gerrand <adg@golang.org> | 2014-08-13 13:20:01 +1000 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2014-08-13 13:20:01 +1000 |
commit | 67fecf733413ef7f6c2ea9fa097ccae47b6b4283 (patch) | |
tree | a2b43858b05ab697f663d3530e107b2512453cb9 | |
parent | e3338c848402d04b92de0477803a77a1de93605b (diff) | |
download | go-67fecf733413ef7f6c2ea9fa097ccae47b6b4283.tar.gz |
[release-branch.go1.3] runtime: fix GC bitmap corruption
??? CL 103640044 / d2f256096d8d
runtime: fix GC bitmap corruption
Fixes issue 8299.
R=golang-codereviews
CC=golang-codereviews, khr, rsc
https://codereview.appspot.com/103640044
???
TBR=r, rsc
CC=golang-codereviews
https://codereview.appspot.com/125150044
-rw-r--r-- | src/pkg/runtime/mgc0.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 392da535b..9b23c53c2 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -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. |