runtime: run init on main thread
Fixes #3125.
R=golang-dev, r, minux.ma
CC=golang-dev
https://golang.org/cl/5714049
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index 761246a..c877bfc 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -326,7 +326,7 @@
}
// Release (part of) unused memory to OS.
-// Goroutine created in runtime·schedinit.
+// Goroutine created at startup.
// Loop forever.
void
runtime·MHeap_Scavenger(void)
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index ddac048..de7090c 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -209,8 +209,6 @@
mstats.enablegc = 1;
m->nomemprof--;
-
- scvg = runtime·newproc1((byte*)runtime·MHeap_Scavenger, nil, 0, 0, runtime·schedinit);
}
extern void main·init(void);
@@ -228,6 +226,7 @@
// to preserve the lock.
runtime·LockOSThread();
runtime·sched.init = true;
+ scvg = runtime·newproc1((byte*)runtime·MHeap_Scavenger, nil, 0, 0, runtime·main);
main·init();
runtime·sched.init = false;
if(!runtime·sched.lockmain)
@@ -587,10 +586,11 @@
mput(m);
}
- // Look for deadlock situation: one single active g which happens to be scvg.
- if(runtime·sched.grunning == 1 && runtime·sched.gwait == 0) {
- if(scvg->status == Grunning || scvg->status == Gsyscall)
- runtime·throw("all goroutines are asleep - deadlock!");
+ // Look for deadlock situation.
+ if((scvg == nil && runtime·sched.grunning == 0) ||
+ (scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
+ (scvg->status == Grunning || scvg->status == Gsyscall))) {
+ runtime·throw("all goroutines are asleep - deadlock!");
}
m->nextg = nil;
diff --git a/src/pkg/runtime/runtime_linux_test.go b/src/pkg/runtime/runtime_linux_test.go
new file mode 100644
index 0000000..5344ed2
--- /dev/null
+++ b/src/pkg/runtime/runtime_linux_test.go
@@ -0,0 +1,29 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ . "runtime"
+ "syscall"
+ "testing"
+)
+
+var pid, tid int
+
+func init() {
+ // Record pid and tid of init thread for use during test.
+ // The call to LockOSThread is just to exercise it;
+ // we can't test that it does anything.
+ // Instead we're testing that the conditions are good
+ // for how it is used in init (must be on main thread).
+ pid, tid = syscall.Getpid(), syscall.Gettid()
+ LockOSThread()
+}
+
+func TestLockOSThread(t *testing.T) {
+ if pid != tid {
+ t.Fatalf("pid=%d but tid=%d", pid, tid)
+ }
+}