Commit 9aa7d136 authored by Russ Cox's avatar Russ Cox

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
parent d8cbbe68
...@@ -2846,9 +2846,12 @@ sysmon(void) ...@@ -2846,9 +2846,12 @@ sysmon(void)
lastgc = runtime·atomicload64(&mstats.last_gc); lastgc = runtime·atomicload64(&mstats.last_gc);
if(lastgc != 0 && unixnow - lastgc > forcegcperiod && runtime·atomicload(&runtime·forcegc.idle)) { if(lastgc != 0 && unixnow - lastgc > forcegcperiod && runtime·atomicload(&runtime·forcegc.idle)) {
runtime·lock(&runtime·forcegc.lock); runtime·lock(&runtime·forcegc.lock);
runtime·forcegc.idle = 0; if(runtime·forcegc.g != nil) {
runtime·forcegc.g->schedlink = nil; // Goroutine may be started but has not initialized g yet.
injectglist(runtime·forcegc.g); runtime·forcegc.idle = 0;
runtime·forcegc.g->schedlink = nil;
injectglist(runtime·forcegc.g);
}
runtime·unlock(&runtime·forcegc.lock); runtime·unlock(&runtime·forcegc.lock);
} }
......
...@@ -31,23 +31,25 @@ var parkunlock_c byte ...@@ -31,23 +31,25 @@ var parkunlock_c byte
// start forcegc helper goroutine // start forcegc helper goroutine
func init() { func init() {
go func() { go forcegchelper()
forcegc.g = getg() }
forcegc.g.issystem = true
for { func forcegchelper() {
lock(&forcegc.lock) forcegc.g = getg()
if forcegc.idle != 0 { forcegc.g.issystem = true
gothrow("forcegc: phase error") for {
} lock(&forcegc.lock)
atomicstore(&forcegc.idle, 1) if forcegc.idle != 0 {
goparkunlock(&forcegc.lock, "force gc (idle)") gothrow("forcegc: phase error")
// this goroutine is explicitly resumed by sysmon
if debug.gctrace > 0 {
println("GC forced")
}
gogc(1)
} }
}() 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 // Gosched yields the processor, allowing other goroutines to run. It does not
......
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