Commit d6d7170d authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: fix data race in stackalloc

Stack shrinking happens during mark phase,
and it assumes that it owns stackcache in mcache.
Stack cache flushing also happens during mark phase,
and it accesses stackcache's w/o any synchronization.
This leads to stackcache corruption:
http://goperfd.appspot.com/log/309af5571dfd7e1817259b9c9cf9bcf9b2c27610

LGTM=khr
R=khr
CC=golang-codereviews, rsc
https://golang.org/cl/126870043
parent a83bbc9c
...@@ -223,9 +223,11 @@ runtime·stackalloc(G *gp, uint32 n) ...@@ -223,9 +223,11 @@ runtime·stackalloc(G *gp, uint32 n)
n2 >>= 1; n2 >>= 1;
} }
c = g->m->mcache; c = g->m->mcache;
if(c == nil) { if(c == nil || g->m->gcing || g->m->helpgc) {
// This can happen in the guts of exitsyscall or // c == nil can happen in the guts of exitsyscall or
// procresize. Just get a stack from the global pool. // procresize. Just get a stack from the global pool.
// Also don't touch stackcache during gc
// as it's flushed concurrently.
runtime·lock(&stackpoolmu); runtime·lock(&stackpoolmu);
x = poolalloc(order); x = poolalloc(order);
runtime·unlock(&stackpoolmu); runtime·unlock(&stackpoolmu);
...@@ -285,7 +287,7 @@ runtime·stackfree(G *gp, void *v, Stktop *top) ...@@ -285,7 +287,7 @@ runtime·stackfree(G *gp, void *v, Stktop *top)
} }
x = (MLink*)v; x = (MLink*)v;
c = g->m->mcache; c = g->m->mcache;
if(c == nil) { if(c == nil || g->m->gcing || g->m->helpgc) {
runtime·lock(&stackpoolmu); runtime·lock(&stackpoolmu);
poolfree(x, order); poolfree(x, order);
runtime·unlock(&stackpoolmu); runtime·unlock(&stackpoolmu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment