From: Dmitriy Vyukov Date: Wed, 23 Jul 2014 14:52:25 +0000 (+0400) Subject: runtime: don't lock mheap on user goroutine X-Git-Tag: go1.4beta1~1023 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e91704af275fc6dcbad8f94fd11baadeb062e50e;p=gostls13.git runtime: don't lock mheap on user goroutine This is bad for 2 reasons: 1. if the code under lock ever grows stack, it will deadlock as stack growing acquires mheap lock. 2. It currently deadlocks with SetCPUProfileRate: scavenger locks mheap, receives prof signal and tries to lock prof lock; meanwhile SetCPUProfileRate locks prof lock and tries to grow stack (presumably in runtime.unlock->futexwakeup). Boom. Let's assume that it Fixes #8407. LGTM=rsc R=golang-codereviews, rsc CC=golang-codereviews, khr https://golang.org/cl/112640043 --- diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c index 202a903ff8..7ae5a399b3 100644 --- a/src/pkg/runtime/mheap.c +++ b/src/pkg/runtime/mheap.c @@ -642,7 +642,6 @@ static FuncVal forcegchelperv = {(void(*)(void))forcegchelper}; void runtime·MHeap_Scavenger(void) { - MHeap *h; uint64 tick, forcegc, limit; int64 unixnow; int32 k; @@ -662,15 +661,12 @@ runtime·MHeap_Scavenger(void) else tick = limit/2; - h = &runtime·mheap; for(k=0;; k++) { runtime·noteclear(¬e); runtime·notetsleepg(¬e, tick); - runtime·lock(h); unixnow = runtime·unixnanotime(); if(unixnow - mstats.last_gc > forcegc) { - runtime·unlock(h); // The scavenger can not block other goroutines, // otherwise deadlock detector can fire spuriously. // GC blocks other goroutines via the runtime·worldsema. @@ -680,13 +676,13 @@ runtime·MHeap_Scavenger(void) runtime·notetsleepg(¬e, -1); if(runtime·debug.gctrace > 0) runtime·printf("scvg%d: GC forced\n", k); - runtime·lock(h); } - runtime·unlock(h); + g->m->locks++; // ensure that we are on the same m while filling arguments g->m->scalararg[0] = k; g->m->scalararg[1] = runtime·nanotime(); g->m->scalararg[2] = limit; runtime·mcall(scavenge_m); + g->m->locks--; } }