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);
}
// 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