]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: avoid race with forcegc helper
authorRuss Cox <rsc@golang.org>
Tue, 2 Sep 2014 23:18:46 +0000 (19:18 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 2 Sep 2014 23:18:46 +0000 (19:18 -0400)
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

src/pkg/runtime/proc.c
src/pkg/runtime/proc.go

index d1ebd853bb45f5bb46477b86b03bf8209865c4ee..9229c53a8c18ff0ad60c892c48a75a227f7f67b2 100644 (file)
@@ -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);
                }
 
index 6c295c7b181498d48179d10559ea4beaed3edbba..d47503e2301647809e920abb6ea354287ba1c849 100644 (file)
@@ -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