From: Russ Cox Date: Tue, 2 Sep 2014 23:18:46 +0000 (-0400) Subject: runtime: avoid race with forcegc helper X-Git-Tag: go1.4beta1~569 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9aa7d136f52928587a6bd2db320f4f4f2b6b0666;p=gostls13.git runtime: avoid race with forcegc helper While we are here, give the gc helper a real function name that will appear in stack traces. LGTM=rlh R=rlh CC=dvyukov, golang-codereviews https://golang.org/cl/133470043 --- diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index d1ebd853bb..9229c53a8c 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -2846,9 +2846,12 @@ sysmon(void) lastgc = runtime·atomicload64(&mstats.last_gc); if(lastgc != 0 && unixnow - lastgc > forcegcperiod && runtime·atomicload(&runtime·forcegc.idle)) { runtime·lock(&runtime·forcegc.lock); - runtime·forcegc.idle = 0; - runtime·forcegc.g->schedlink = nil; - injectglist(runtime·forcegc.g); + if(runtime·forcegc.g != nil) { + // Goroutine may be started but has not initialized g yet. + runtime·forcegc.idle = 0; + runtime·forcegc.g->schedlink = nil; + injectglist(runtime·forcegc.g); + } runtime·unlock(&runtime·forcegc.lock); } diff --git a/src/pkg/runtime/proc.go b/src/pkg/runtime/proc.go index 6c295c7b18..d47503e230 100644 --- a/src/pkg/runtime/proc.go +++ b/src/pkg/runtime/proc.go @@ -31,23 +31,25 @@ var parkunlock_c byte // start forcegc helper goroutine func init() { - go func() { - forcegc.g = getg() - forcegc.g.issystem = true - for { - lock(&forcegc.lock) - if forcegc.idle != 0 { - gothrow("forcegc: phase error") - } - atomicstore(&forcegc.idle, 1) - goparkunlock(&forcegc.lock, "force gc (idle)") - // this goroutine is explicitly resumed by sysmon - if debug.gctrace > 0 { - println("GC forced") - } - gogc(1) + go forcegchelper() +} + +func forcegchelper() { + forcegc.g = getg() + forcegc.g.issystem = true + for { + lock(&forcegc.lock) + if forcegc.idle != 0 { + gothrow("forcegc: phase error") } - }() + atomicstore(&forcegc.idle, 1) + goparkunlock(&forcegc.lock, "force gc (idle)") + // this goroutine is explicitly resumed by sysmon + if debug.gctrace > 0 { + println("GC forced") + } + gogc(1) + } } // Gosched yields the processor, allowing other goroutines to run. It does not