]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: lock the main goroutine to the main OS thread during init
authorRuss Cox <rsc@golang.org>
Fri, 28 Oct 2011 01:04:12 +0000 (18:04 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 28 Oct 2011 01:04:12 +0000 (18:04 -0700)
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

src/pkg/runtime/386/asm.s
src/pkg/runtime/amd64/asm.s
src/pkg/runtime/arm/asm.s
src/pkg/runtime/debug.go
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h

index 40cef0c1c2e6c72571300e04a0a5dca33a12535d..bafef01c7eb3dc8490bf784d3e5bdb336d494047 100644 (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
index f34ce4a8839b85392e71f142d30862bdfe9e9dd3..866e083106a2bdfc839cf6109d55d98caf92ca4f 100644 (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
index a427a465f98231bf60c1871003edbb706812e6cd..c03422f10c8118d48c798b8bc66f16ad7def7eed 100644 (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
index 6370a57d8029a31de8b06b83e823d13e0a6d6ca0..124370384c095ebfc46f5059ef89a50913021b01 100644 (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.
index 3408c06f69f12c08f88d073586483e9d91922dd0..d51e3d352222dc9962708352dcac105e7061e9af 100644 (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;
 }
index e3ec197757aa005607fe5110f2e553ec239220ce..e45808f8e0e8868c124a6991c283936e31d29eea 100644 (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*);