From: Russ Cox A
's initializer calls a function defined
in another package that refers to B
.
-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. -
-
An init
function cannot be referred to from anywhere
in a program. In particular, init
cannot be called explicitly,
nor can a pointer to init
be assigned to a function variable.
diff --git a/src/pkg/runtime/386/asm.s b/src/pkg/runtime/386/asm.s
index c64e78f59f..40cef0c1c2 100644
--- a/src/pkg/runtime/386/asm.s
+++ b/src/pkg/runtime/386/asm.s
@@ -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)
diff --git a/src/pkg/runtime/amd64/asm.s b/src/pkg/runtime/amd64/asm.s
index a881e3bbf4..f34ce4a883 100644
--- a/src/pkg/runtime/amd64/asm.s
+++ b/src/pkg/runtime/amd64/asm.s
@@ -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)
diff --git a/src/pkg/runtime/arm/asm.s b/src/pkg/runtime/arm/asm.s
index 63153658f1..a427a465f9 100644
--- a/src/pkg/runtime/arm/asm.s
+++ b/src/pkg/runtime/arm/asm.s
@@ -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)
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 5a9d477bc7..468960d177 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -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
index 0000000000..9ce3c12ee6
--- /dev/null
+++ b/test/init1.go
@@ -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() {
+}
+