]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: run goroutines during init
authorRuss Cox <rsc@golang.org>
Thu, 13 Oct 2011 19:54:23 +0000 (15:54 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 13 Oct 2011 19:54:23 +0000 (15:54 -0400)
Fixes #583.
Fixes #1776.
Fixes #2001.
Fixes #2112.

R=golang-dev, bradfitz, r, gri
CC=golang-dev
https://golang.org/cl/5265044

doc/go_spec.html
src/pkg/runtime/386/asm.s
src/pkg/runtime/amd64/asm.s
src/pkg/runtime/arm/asm.s
src/pkg/runtime/proc.c
test/init1.go [new file with mode: 0644]

index 395d21828fe7ba2f7ba19df35c1e59eb514cb111..13f52996c4dcb5ccbdce21efe30e64f413581aa5 100644 (file)
@@ -5109,12 +5109,6 @@ unspecified results  if <code>A</code>'s initializer calls a function defined
 in another package that refers to <code>B</code>.
 </p>
 <p>
-Initialization code may contain "go" statements, but the functions
-they invoke do not begin execution until initialization of the entire
-program is complete. Therefore, all initialization code is run in a single
-goroutine.
-</p>
-<p>
 An <code>init</code> function cannot be referred to from anywhere
 in a program. In particular, <code>init</code> cannot be called explicitly,
 nor can a pointer to <code>init</code> be assigned to a function variable.
index c64e78f59f5fbc23f7ed0a2c1f297947384318b8..40cef0c1c2e6c72571300e04a0a5dca33a12535d 100644 (file)
@@ -92,7 +92,6 @@ ok:
 
 TEXT runtime·mainstart(SB),7,$0
        CALL    main·init(SB)
-       CALL    runtime·initdone(SB)
        CALL    main·main(SB)
        PUSHL   $0
        CALL    runtime·exit(SB)
index a881e3bbf46a84eec13512aed5702a35c4496748..f34ce4a8839b85392e71f142d30862bdfe9e9dd3 100644 (file)
@@ -74,7 +74,6 @@ ok:
 
 TEXT runtime·mainstart(SB),7,$0
        CALL    main·init(SB)
-       CALL    runtime·initdone(SB)
        CALL    main·main(SB)
        PUSHQ   $0
        CALL    runtime·exit(SB)
index 63153658f1fcb0b5abd195902165408d53c23553..a427a465f98231bf60c1871003edbb706812e6cd 100644 (file)
@@ -63,7 +63,6 @@ TEXT _rt0_arm(SB),7,$-4
 
 TEXT runtime·mainstart(SB),7,$4
        BL      main·init(SB)
-       BL      runtime·initdone(SB)
        EOR     R0, R0
        MOVW    R0, 0(R13)
        BL      main·main(SB)
index 5a9d477bc7711d6f8e1a65d2885126a8c7d5eb03..468960d17729be3924d87fffc816565a4621ce1e 100644 (file)
@@ -71,7 +71,6 @@ struct Sched {
 
        volatile uint32 atomic; // atomic scheduling word (see below)
 
-       int32 predawn;          // running initialization, don't run new g's.
        int32 profilehz;        // cpu profiling rate
 
        Note    stopped;        // one g can set waitstop and wait here for m's to stop
@@ -202,8 +201,8 @@ runtime·schedinit(void)
        }
        setmcpumax(runtime·gomaxprocs);
        runtime·singleproc = runtime·gomaxprocs == 1;
-       runtime·sched.predawn = 1;
 
+       mstats.enablegc = 1;
        m->nomemprof--;
 }
 
@@ -227,22 +226,6 @@ schedunlock(void)
                runtime·notewakeup(&m->havenextg);
 }
 
-// Called after main·init_function; main·main will be called on return.
-void
-runtime·initdone(void)
-{
-       // Let's go.
-       runtime·sched.predawn = 0;
-       mstats.enablegc = 1;
-
-       // If main·init_function started other goroutines,
-       // kick off new m's to handle them, like ready
-       // would have, had it not been pre-dawn.
-       schedlock();
-       matchmg();
-       schedunlock();
-}
-
 void
 runtime·goexit(void)
 {
@@ -467,8 +450,7 @@ readylocked(G *g)
        g->status = Grunnable;
 
        gput(g);
-       if(!runtime·sched.predawn)
-               matchmg();
+       matchmg();
 }
 
 static void
@@ -793,9 +775,6 @@ schedule(G *gp)
 
        schedlock();
        if(gp != nil) {
-               if(runtime·sched.predawn)
-                       runtime·throw("init rescheduling");
-
                // Just finished running gp.
                gp->m = nil;
                runtime·sched.grunning--;
@@ -893,9 +872,6 @@ runtime·entersyscall(void)
 {
        uint32 v;
 
-       if(runtime·sched.predawn)
-               return;
-
        // Leave SP around for gc and traceback.
        runtime·gosave(&g->sched);
        g->gcsp = g->sched.sp;
@@ -947,9 +923,6 @@ runtime·exitsyscall(void)
 {
        uint32 v;
 
-       if(runtime·sched.predawn)
-               return;
-
        // Fast path.
        // If we can do the mcpu++ bookkeeping and
        // find that we still have mcpu <= mcpumax, then we can
@@ -1513,8 +1486,6 @@ runtime·Gosched(void)
 void
 runtime·LockOSThread(void)
 {
-       if(runtime·sched.predawn)
-               runtime·throw("cannot wire during init");
        m->lockedg = g;
        g->lockedm = m;
 }
diff --git a/test/init1.go b/test/init1.go
new file mode 100644 (file)
index 0000000..9ce3c12
--- /dev/null
@@ -0,0 +1,44 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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.
+
+// Test that goroutines and garbage collection run during init.
+
+package main
+
+import "runtime"
+
+var x []byte
+
+func init() {
+       c := make(chan int)
+       go send(c)
+       <-c
+       
+       const chunk = 1<<20
+       runtime.UpdateMemStats()
+       sys := runtime.MemStats.Sys     
+       b := make([]byte, chunk)
+       for i := range b {
+               b[i] = byte(i%10 + '0')
+       }
+       s := string(b)
+       for i := 0; i < 1000; i++ {
+               x = []byte(s)
+       }
+       runtime.UpdateMemStats()
+       sys1 := runtime.MemStats.Sys
+       if sys1-sys > chunk*50 {
+               println("allocated 1000 chunks of", chunk, "and used ", sys1-sys, "memory")
+       }
+}
+
+func send(c chan int) {
+       c <- 1
+}
+
+func main() {
+}
+