aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/stack.c
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2014-08-08 20:13:57 +0400
committerDmitriy Vyukov <dvyukov@google.com>2014-08-08 20:13:57 +0400
commitd6d7170de414c16a7ea0125b5a458272557227b6 (patch)
treed64418ad748b85a19ece7c72e50de5e04a88cedf /src/pkg/runtime/stack.c
parenta83bbc9c488fb5b5405a5d1dc13a32d588a2fccd (diff)
downloadgo-d6d7170de414c16a7ea0125b5a458272557227b6.tar.xz
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
Diffstat (limited to 'src/pkg/runtime/stack.c')
-rw-r--r--src/pkg/runtime/stack.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c
index 0a806e8fab..772080af55 100644
--- a/src/pkg/runtime/stack.c
+++ b/src/pkg/runtime/stack.c
@@ -223,9 +223,11 @@ runtime·stackalloc(G *gp, uint32 n)
n2 >>= 1;
}
c = g->m->mcache;
- if(c == nil) {
- // This can happen in the guts of exitsyscall or
+ if(c == nil || g->m->gcing || g->m->helpgc) {
+ // c == nil can happen in the guts of exitsyscall or
// procresize. Just get a stack from the global pool.
+ // Also don't touch stackcache during gc
+ // as it's flushed concurrently.
runtime·lock(&stackpoolmu);
x = poolalloc(order);
runtime·unlock(&stackpoolmu);
@@ -285,7 +287,7 @@ runtime·stackfree(G *gp, void *v, Stktop *top)
}
x = (MLink*)v;
c = g->m->mcache;
- if(c == nil) {
+ if(c == nil || g->m->gcing || g->m->helpgc) {
runtime·lock(&stackpoolmu);
poolfree(x, order);
runtime·unlock(&stackpoolmu);