]> Cypherpunks repositories - gostls13.git/commitdiff
proper handling of signals.
authorRuss Cox <rsc@golang.org>
Thu, 18 Sep 2008 22:56:46 +0000 (15:56 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 18 Sep 2008 22:56:46 +0000 (15:56 -0700)
do not run init on g0.

R=r
DELTA=161  (124 added, 23 deleted, 14 changed)
OCL=15490
CL=15497

src/runtime/proc.c
src/runtime/rt0_amd64.s
src/runtime/rt1_amd64_darwin.c
src/runtime/rt1_amd64_linux.c
src/runtime/runtime.h
src/runtime/string.c
src/runtime/sys_amd64_darwin.s
src/runtime/sys_amd64_linux.s

index 62efd4569103230c52138e47fe64de862097d027..84f5a06ed66567ab5c53808f9e3400d213ed1bd3 100644 (file)
@@ -70,7 +70,18 @@ static void readylocked(G*); // ready, but sched is locked
 // Scheduler loop.
 static void scheduler(void);
 
-// Called before main·init_function.
+// The bootstrap sequence is:
+//
+//     call osinit
+//     call schedinit
+//     make & queue new G
+//     call mstart
+//
+// The new G does:
+//
+//     call main·init_function
+//     call initdone
+//     call main·main
 void
 schedinit(void)
 {
@@ -85,9 +96,9 @@ schedinit(void)
        sched.predawn = 1;
 }
 
-// Called after main·init_function; main·main is on ready queue.
+// Called after main·init_function; main·main will be called on return.
 void
-m0init(void)
+initdone(void)
 {
        int32 i;
 
@@ -100,8 +111,6 @@ m0init(void)
        // would have, had it not been pre-dawn.
        for(i=1; i<sched.gcount && i<sched.mmax; i++)
                mnew();
-
-       scheduler();
 }
 
 void
@@ -116,6 +125,21 @@ sys·goexit(void)
        sys·gosched();
 }
 
+G*
+malg(int32 stacksize)
+{
+       G *g;
+       byte *stk;
+
+       // 160 is the slop amount known to the stack growth code
+       g = mal(sizeof(G));
+       stk = mal(160 + stacksize);
+       g->stack0 = stk;
+       g->stackguard = stk + 160;
+       g->stackbase = stk + 160 + stacksize;
+       return g;
+}
+
 void
 sys·newproc(int32 siz, byte* fn, byte* arg0)
 {
@@ -135,15 +159,13 @@ sys·newproc(int32 siz, byte* fn, byte* arg0)
 
        if((newg = gfget()) != nil){
                newg->status = Gwaiting;
-               stk = newg->stack0;
        }else{
-               newg = mal(sizeof(G));
-               stk = mal(4096);
-               newg->stack0 = stk;
+               newg = malg(4096);
                newg->status = Gwaiting;
                newg->alllink = allg;
                allg = newg;
        }
+       stk = newg->stack0;
 
        newg->stackguard = stk+160;
 
@@ -335,6 +357,14 @@ nextgandunlock(void)
        return gp;
 }
 
+// Called to start an M.
+void
+mstart(void)
+{
+       minit();
+       scheduler();
+}
+
 // Scheduler loop: find g to run, run it, repeat.
 static void
 scheduler(void)
@@ -342,11 +372,13 @@ scheduler(void)
        G* gp;
 
        lock(&sched);
-
        if(gosave(&m->sched)){
-               // Jumped here via gosave/gogo, so didn'
+               // Jumped here via gosave/gogo, so didn't
                // execute lock(&sched) above.
                lock(&sched);
+               
+               if(sched.predawn)
+                       throw("init sleeping");
 
                // Just finished running m->curg.
                gp = m->curg;
@@ -371,7 +403,6 @@ scheduler(void)
 
        // Find (or wait for) g to run.  Unlocks sched.
        gp = nextgandunlock();
-
        noteclear(&gp->stopped);
        gp->status = Grunning;
        m->curg = gp;
@@ -388,10 +419,6 @@ void
 sys·gosched(void)
 {
        if(gosave(&g->sched) == 0){
-               // TODO(rsc) signal race here?
-               // If a signal comes in between
-               // changing g and changing SP,
-               // growing the stack will fail.
                g = m->g0;
                gogo(&m->sched);
        }
@@ -402,8 +429,6 @@ static void
 mnew(void)
 {
        M *m;
-       G *g;
-       byte *stk, *stktop;
 
        sched.mcount++;
        if(debug){
@@ -411,18 +436,9 @@ mnew(void)
                prints(" threads\n");
        }
 
-       // Allocate m, g, stack in one chunk.
-       // 1024 and 104 are the magic constants
-       // use in rt0_amd64.s when setting up g0.
-       m = mal(sizeof(M)+sizeof(G)+104+1024);
-       g = (G*)(m+1);
-       stk = (byte*)g + 104;
-       stktop = stk + 1024;
-
-       m->g0 = g;
-       g->stackguard = stk;
-       g->stackbase = stktop;
-       newosproc(m, g, stktop, scheduler);
+       m = mal(sizeof(M));
+       m->g0 = malg(1024);
+       newosproc(m, m->g0, m->g0->stackbase, mstart);
 }
 
 //
index 0200f35f481a09b837eb05817a439b98bbd97490..9f354a71aecc087ebbcbbd0d54f6f3b42ee4d0cc 100644 (file)
@@ -35,20 +35,25 @@ TEXT        _rt0_amd64(SB),7,$-8
        CALL    args(SB)
        CALL    osinit(SB)
        CALL    schedinit(SB)
-       CALL    main·init_function(SB) // initialization
 
        // create a new goroutine to start program
 
-       PUSHQ   $main·main(SB)         // entry
+       PUSHQ   $mainstart(SB)          // entry
        PUSHQ   $16                     // arg size
        CALL    sys·newproc(SB)
-       CALL    m0init(SB)
+       CALL    mstart(SB)
        POPQ    AX
        POPQ    AX
 
        CALL    notok(SB)               // never returns
        RET
 
+TEXT mainstart(SB),7,$0
+       CALL    main·init_function(SB)
+       CALL    initdone(SB)
+       CALL    main·main(SB)
+       RET
+
 TEXT   sys·breakpoint(SB),7,$0
        BYTE    $0xcc
        RET
index f8718aed3b021dd78d6c322db6caeb5993af90a4..cf4f3bcdadb307a2bbb4eefbcab48cd1c487c2b6 100644 (file)
@@ -157,16 +157,33 @@ sighandler(int32 sig, siginfo *info, void *context)
        sys·exit(2);
 }
 
+struct stack_t {
+       byte *sp;
+       int64 size;
+       int32 flags;
+};
 
 sigaction a;
 extern void sigtramp(void);
 
+void
+signalstack(byte *p, int32 n)
+{
+       struct stack_t st;
+
+       st.sp = p;
+       st.size = n;
+       st.flags = 0;
+       sigaltstack(&st, nil);
+}
+
 void
 initsig(void)
 {
        int32 i;
+
        a.u.sa_sigaction = (void*)sigtramp;
-       a.sa_flags |= 0x40;  /* SA_SIGINFO */
+       a.sa_flags |= 0x41;  /* SA_SIGINFO, SA_ONSTACK */
        for(i=0; i<sizeof(a.sa_mask); i++)
                a.sa_mask[i] = 0xFF;
        a.sa_trampoline = sigtramp;
@@ -308,6 +325,15 @@ newosproc(M *m, G *g, void *stk, void (*fn)(void))
        bsdthread_create(stk, m, g, fn);
 }
 
+// Called to initialize a new m (including the bootstrap m).
+void
+minit(void)
+{
+       // Initialize signal handling.
+       m->gsignal = malg(32*1024);     // OS X wants >=8K, Linux >=2K
+       signalstack(m->gsignal->stackguard, 32*1024);
+}
+
 
 // Mach IPC, to get at semaphores
 // Definitions are in /usr/include/mach on a Mac.
index 54b6496d1cba5c32099868e73fea9afc50918b95..c62db5ce9567e0320a317168281fda31300120c5 100644 (file)
@@ -161,6 +161,25 @@ sighandler(int32 sig, siginfo* info, void** context)
        sys·exit(2);
 }
 
+struct stack_t {
+       void *sp;
+       int32 flags;
+       int32 pad;
+       int64 size;
+};
+
+void
+signalstack(byte *p, int32 n)
+{
+       struct stack_t st;
+
+       st.sp = p;
+       st.size = n;
+       st.pad = 0;
+       st.flags = 0;
+       sigaltstack(&st, nil);
+}
+
 static sigaction a;
 
 void
@@ -168,7 +187,7 @@ initsig(void)
 {
        int32 i;
        a.u.sa_sigaction = (void*)sigtramp;
-       a.sa_flags = 0x04;  /* SA_SIGINFO */
+       a.sa_flags = 0x08000004;  /* SA_ONSTACK,  SA_SIGINFO */
        for(i=0; i<sizeof(a.sa_mask); i++)
                a.sa_mask[i] = 0xFF;
 
@@ -178,6 +197,7 @@ initsig(void)
                }
 }
 
+
 // Linux futex.
 //
 //     futexsleep(uint32 *addr, uint32 val)
@@ -432,3 +452,12 @@ void
 osinit(void)
 {
 }
+
+// Called to initialize a new m (including the bootstrap m).
+void
+minit(void)
+{
+       // Initialize signal handling.
+       m->gsignal = malg(32*1024);     // OS X wants >=8K, Linux >=2K
+       signalstack(m->gsignal->stackguard, 32*1024);
+}
index 022789234d2bdf0433432bee2d4148e51be64a17..8ead7dd237e26d96026095bf9aa528a8ea5e6ec1 100644 (file)
@@ -157,6 +157,7 @@ struct      M
        uint64  morearg;        // arg to morestack - must not move
        uint64  cret;           // return value from C - must not move
        uint64  procid; // for debuggers - must not move
+       G*      gsignal;                // signal-handling G - must not move
        G*      curg;           // current running goroutine
        G*      lastg;          // last running goroutine - to emulate fifo
        Gobuf   sched;
@@ -248,6 +249,10 @@ void       ready(G*);
 byte*  getenv(int8*);
 int32  atoi(byte*);
 void   newosproc(M *m, G *g, void *stk, void (*fn)(void));
+void   sigaltstack(void*, void*);
+void   signalstack(byte*, int32);
+G*     malg(int32);
+void   minit(void);
 
 /*
  * mutual exclusion locks.  in the uncontended case,
index 099d7aa1d163e55617671717a75df07ce94e6f3c..27a75810946053c3ba84a064472e80f66c3fe3ff 100644 (file)
@@ -53,7 +53,7 @@ prbounds(int8* s, int32 a, int32 b, int32 c)
        prints(">");
        sys·printint(c);
        prints("\n");
-       throw("bounds");
+       throw("string bounds");
 }
 
 uint32
index 19d8184efbf006fab24e61ea8fda94f1b0618581..b690e3108ae586a3e8a85b2acf6929349476f3cb 100644 (file)
@@ -86,6 +86,7 @@ TEXT  sys·sigaction(SB),7,$-8
        RET
 
 TEXT sigtramp(SB),7,$24
+       MOVQ    32(R14), R15    // g = m->gsignal
        MOVL    DX,0(SP)
        MOVQ    CX,8(SP)
        MOVQ    R8,16(SP)
@@ -132,6 +133,15 @@ TEXT       sys·setcallerpc+0(SB),7,$0
        MOVQ    BX, -8(AX)              // set calling pc
        RET
 
+TEXT sigaltstack(SB),7,$-8
+       MOVQ    new+8(SP), DI
+       MOVQ    old+16(SP), SI
+       MOVQ    $(0x2000000+53), AX
+       SYSCALL
+       JCC     2(PC)
+       CALL    notok(SB)
+       RET
+
 // void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
 TEXT bsdthread_create(SB),7,$-8
        // Set up arguments to bsdthread_create system call.
index 01f6f6280d8c7b8f625642fd0cdef0e0a20be0e5..766ee8c9f56c2166efbd0d8396b702442320c430 100644 (file)
@@ -73,6 +73,7 @@ TEXT  sys·rt_sigaction(SB),7,$0-32
        RET
 
 TEXT   sigtramp(SB),7,$24-16
+       MOVQ    32(R14), R15    // g = m->gsignal
        MOVQ    DI,0(SP)
        MOVQ    SI,8(SP)
        MOVQ    DX,16(SP)
@@ -192,3 +193,12 @@ TEXT select(SB),7,$0
        SYSCALL
        RET
 
+TEXT sigaltstack(SB),7,$-8
+       MOVQ    new+8(SP), DI
+       MOVQ    old+16(SP), SI
+       MOVQ    $131, AX
+       SYSCALL
+       CMPQ    AX, $0xfffffffffffff001
+       JLS     2(PC)
+       CALL    notok(SB)
+       RET