runtime: lock the main goroutine to the main OS thread during init

We only guarantee that the main goroutine runs on the
main OS thread for initialization.  Programs that wish to
preserve that property for main.main can call runtime.LockOSThread.
This is what programs used to do before we unleashed
goroutines during init, so it is both a simple fix and keeps
existing programs working.

R=iant, r, dave, dvyukov
CC=golang-dev
https://golang.org/cl/5309070
This commit is contained in:
Russ Cox 2011-10-27 18:04:12 -07:00
parent 32f3770ec5
commit 6808da0163
6 changed files with 50 additions and 48 deletions

View file

@ -78,7 +78,7 @@ ok:
CALL runtime·schedinit(SB)
// create a new goroutine to start program
PUSHL $runtime·mainstart(SB) // entry
PUSHL $runtime·main(SB) // entry
PUSHL $0 // arg size
CALL runtime·newproc(SB)
POPL AX
@ -90,15 +90,6 @@ ok:
INT $3
RET
TEXT runtime·mainstart(SB),7,$0
CALL main·init(SB)
CALL main·main(SB)
PUSHL $0
CALL runtime·exit(SB)
POPL AX
INT $3
RET
TEXT runtime·breakpoint(SB),7,$0
INT $3
RET

View file

@ -60,7 +60,7 @@ ok:
CALL runtime·schedinit(SB)
// create a new goroutine to start program
PUSHQ $runtime·mainstart(SB) // entry
PUSHQ $runtime·main(SB) // entry
PUSHQ $0 // arg size
CALL runtime·newproc(SB)
POPQ AX
@ -72,15 +72,6 @@ ok:
CALL runtime·notok(SB) // never returns
RET
TEXT runtime·mainstart(SB),7,$0
CALL main·init(SB)
CALL main·main(SB)
PUSHQ $0
CALL runtime·exit(SB)
POPQ AX
CALL runtime·notok(SB)
RET
TEXT runtime·breakpoint(SB),7,$0
BYTE $0xcc
RET

View file

@ -43,7 +43,7 @@ TEXT _rt0_arm(SB),7,$-4
BL runtime·schedinit(SB)
// create a new goroutine to start program
MOVW $runtime·mainstart(SB), R0
MOVW $runtime·main(SB), R0
MOVW.W R0, -4(R13)
MOVW $8, R0
MOVW.W R0, -4(R13)
@ -60,20 +60,6 @@ TEXT _rt0_arm(SB),7,$-4
MOVW R0, (R1) // fail hard
B runtime·_dep_dummy(SB) // Never reached
TEXT runtime·mainstart(SB),7,$4
BL main·init(SB)
EOR R0, R0
MOVW R0, 0(R13)
BL main·main(SB)
MOVW $0, R0
MOVW R0, 4(SP)
BL runtime·exit(SB)
MOVW $1234, R0
MOVW $1001, R1
MOVW R0, (R1) // fail hard
RET
// TODO(kaib): remove these once i actually understand how the linker removes symbols
// pull in dummy dependencies
TEXT runtime·_dep_dummy(SB),7,$0

View file

@ -10,7 +10,6 @@ func Breakpoint()
// LockOSThread wires the calling goroutine to its current operating system thread.
// Until the calling goroutine exits or calls UnlockOSThread, it will always
// execute in that thread, and no other goroutine can.
// LockOSThread cannot be used during init functions.
func LockOSThread()
// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.

View file

@ -72,6 +72,9 @@ struct Sched {
volatile uint32 atomic; // atomic scheduling word (see below)
int32 profilehz; // cpu profiling rate
bool init; // running initialization
bool lockmain; // init called runtime.LockOSThread
Note stopped; // one g can set waitstop and wait here for m's to stop
};
@ -171,11 +174,7 @@ setmcpumax(uint32 n)
// make & queue new G
// call runtime·mstart
//
// The new G does:
//
// call main·init_function
// call initdone
// call main·main
// The new G calls runtime·main.
void
runtime·schedinit(void)
{
@ -212,6 +211,32 @@ runtime·schedinit(void)
m->nomemprof--;
}
extern void main·init(void);
extern void main·main(void);
// The main goroutine.
void
runtime·main(void)
{
// Lock the main goroutine onto this, the main OS thread,
// during initialization. Most programs won't care, but a few
// do require certain calls to be made by the main thread.
// Those can arrange for main.main to run in the main thread
// by calling runtime.LockOSThread during initialization
// to preserve the lock.
runtime·LockOSThread();
runtime·sched.init = true;
main·init();
runtime·sched.init = false;
if(!runtime·sched.lockmain)
runtime·UnlockOSThread();
main·main();
runtime·exit(0);
for(;;)
*(int32*)runtime·main = 0;
}
// Lock the scheduler.
static void
schedlock(void)
@ -1494,13 +1519,6 @@ runtime·Gosched(void)
runtime·gosched();
}
void
runtime·LockOSThread(void)
{
m->lockedg = g;
g->lockedm = m;
}
// delete when scheduler is stronger
int32
runtime·gomaxprocsfunc(int32 n)
@ -1540,9 +1558,24 @@ runtime·gomaxprocsfunc(int32 n)
return ret;
}
void
runtime·LockOSThread(void)
{
if(m == &runtime·m0 && runtime·sched.init) {
runtime·sched.lockmain = true;
return;
}
m->lockedg = g;
g->lockedm = m;
}
void
runtime·UnlockOSThread(void)
{
if(m == &runtime·m0 && runtime·sched.init) {
runtime·sched.lockmain = false;
return;
}
m->lockedg = nil;
g->lockedm = nil;
}

View file

@ -637,6 +637,8 @@ String runtime·signame(int32 sig);
int32 runtime·gomaxprocsfunc(int32 n);
void runtime·procyield(uint32);
void runtime·osyield(void);
void runtime·LockOSThread(void);
void runtime·UnlockOSThread(void);
void runtime·mapassign(MapType*, Hmap*, byte*, byte*);
void runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);