From: Russ Cox Date: Thu, 13 Oct 2011 19:54:23 +0000 (-0400) Subject: runtime: run goroutines during init X-Git-Tag: weekly.2011-10-18~88 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d1bafffa4b3d34e4f9b77d02c5c5af1d03f86689;p=gostls13.git runtime: run goroutines during init Fixes #583. Fixes #1776. Fixes #2001. Fixes #2112. R=golang-dev, bradfitz, r, gri CC=golang-dev https://golang.org/cl/5265044 --- diff --git a/doc/go_spec.html b/doc/go_spec.html index 395d21828f..13f52996c4 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -5109,12 +5109,6 @@ unspecified results if 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() { +} +