]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: run sighandler on g0 stack on windows
authorRuss Cox <rsc@golang.org>
Mon, 8 Sep 2014 20:56:46 +0000 (16:56 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 8 Sep 2014 20:56:46 +0000 (16:56 -0400)
The sighander has been run at the bottom of the
currently executing goroutine stack, but it's in C,
and we don't want C on our ordinary goroutine stacks.
Worse, it does a lot of stuff, and it might need more
stack space. There is scary code in traceback_windows.go
that talks about stack splits during sighandler.
Moving sighandler to g0 will eliminate the possibility
of stack splits and such, and then we can delete
traceback_windows.go entirely. Win win.

On the builder, all.bat passes with GOARCH=amd64
and all.bat gets most of the way with GOARCH=386
except for a DLL-loading test that I think is unrelated.

Fixes windows build.

TBR=brainman, iant
CC=golang-codereviews
https://golang.org/cl/140380043

src/runtime/sys_windows_386.s
src/runtime/sys_windows_amd64.s

index a9e096f018f6a4184f48e6e7eb4361227949a68a..7d4dc6a69cd3a784daf1083d0e8f3a7240f7f6ea 100644 (file)
@@ -76,7 +76,7 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0
 // Return 0 for 'not handled', -1 for handled.
 TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVL    ptrs+0(FP), CX
-       SUBL    $32, SP
+       SUBL    $40, SP
 
        // save callee-saved registers
        MOVL    BX, 28(SP)
@@ -84,10 +84,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVL    SI, 20(SP)
        MOVL    DI, 24(SP)
 
-       MOVL    0(CX), BX // ExceptionRecord*
-       MOVL    4(CX), CX // Context*
-
-       // fetch g
+       // find g
        get_tls(DX)
        CMPL    DX, $0
        JNE     3(PC)
@@ -97,6 +94,35 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        CMPL    DX, $0
        JNE     2(PC)
        CALL    runtime·badsignal2(SB)
+
+       // save g and SP in case of stack switch
+       MOVL    DX, 32(SP)      // g
+       MOVL    SP, 36(SP)
+
+       // do we need to switch to the g0 stack?
+       MOVL    g_m(DX), BX
+       MOVL    m_g0(BX), BX
+       CMPL    DX, BX
+       JEQ     sigtramp_g0
+
+       // switch to the g0 stack
+       get_tls(BP)
+       MOVL    BX, g(BP)
+       MOVL    (g_sched+gobuf_sp)(BX), DI
+       // make it look like mstart called us on g0, to stop traceback
+       SUBL    $4, DI
+       MOVL    $runtime·mstart(SB), 0(DI)
+       // traceback will think that we've done SUBL
+       // on this stack, so subtract them here to match.
+       // (we need room for sighandler arguments anyway).
+       // and re-save old SP for restoring later.
+       SUBL    $40, DI
+       MOVL    SP, 36(DI)
+       MOVL    DI, SP
+
+sigtramp_g0:
+       MOVL    0(CX), BX // ExceptionRecord*
+       MOVL    4(CX), CX // Context*
        // call sighandler(ExceptionRecord*, Context*, G*)
        MOVL    BX, 0(SP)
        MOVL    CX, 4(SP)
@@ -105,6 +131,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        // AX is set to report result back to Windows
        MOVL    12(SP), AX
 
+       // switch back to original stack and g
+       // no-op if we never left.
+       MOVL    36(SP), SP
+       MOVL    32(SP), DX
+       get_tls(BP)
+       MOVL    DX, g(BP)
+
 done:
        // restore callee-saved registers
        MOVL    24(SP), DI
@@ -112,7 +145,7 @@ done:
        MOVL    16(SP), BP
        MOVL    28(SP), BX
 
-       ADDL    $32, SP
+       ADDL    $40, SP
        // RET 4 (return and pop 4 bytes parameters)
        BYTE $0xC2; WORD $4
        RET // unreached; make assembler happy
@@ -128,7 +161,7 @@ TEXT runtime·profileloop(SB),NOSPLIT,$0
        PUSHL   $runtime·profileloop1(SB)
        CALL    runtime·externalthreadhandler(SB)
        MOVL    4(SP), CX
-       ADDL    $12, SP
+       ADDL    $40, SP
        JMP     CX
 
 TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
index 21f73daf098764551193634f8065f41f376bcfb2..3d63a04de994f4e647b7007a870026cc0b677066 100644 (file)
@@ -106,7 +106,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
        // as required by windows callback convention.
        PUSHFQ
-       SUBQ    $96, SP
+       SUBQ    $112, SP
        MOVQ    DI, 80(SP)
        MOVQ    SI, 72(SP)
        MOVQ    BP, 64(SP)
@@ -116,10 +116,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVQ    R14, 32(SP)
        MOVQ    R15, 88(SP)
 
-       MOVQ    0(CX), BX // ExceptionRecord*
-       MOVQ    8(CX), CX // Context*
-
-       // fetch g
+       // find g
        get_tls(DX)
        CMPQ    DX, $0
        JNE     3(PC)
@@ -129,6 +126,37 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        CMPQ    DX, $0
        JNE     2(PC)
        CALL    runtime·badsignal2(SB)
+
+       // save g and SP in case of stack switch
+       MOVQ    DX, 96(SP) // g
+       MOVQ    SP, 104(SP)
+
+       // do we need to switch to the g0 stack?
+       MOVQ    g_m(DX), BX
+       MOVQ    m_g0(BX), BX
+       CMPQ    DX, BX
+       JEQ     sigtramp_g0
+
+       // switch to g0 stack
+       get_tls(BP)
+       MOVQ    BX, g(BP)
+       MOVQ    (g_sched+gobuf_sp)(BX), DI
+       // make it look like mstart called us on g0, to stop traceback
+       SUBQ    $8, DI
+       MOVQ    $runtime·mstart(SB), SI
+       MOVQ    SI, 0(DI)
+       // traceback will think that we've done PUSHFQ and SUBQ
+       // on this stack, so subtract them here to match.
+       // (we need room for sighandler arguments anyway).
+       // and re-save old SP for restoring later.
+       SUBQ    $(112+8), DI
+       // save g, save old stack pointer.
+       MOVQ    SP, 104(DI)
+       MOVQ    DI, SP
+
+sigtramp_g0:
+       MOVQ    0(CX), BX // ExceptionRecord*
+       MOVQ    8(CX), CX // Context*
        // call sighandler(ExceptionRecord*, Context*, G*)
        MOVQ    BX, 0(SP)
        MOVQ    CX, 8(SP)
@@ -137,6 +165,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        // AX is set to report result back to Windows
        MOVL    24(SP), AX
 
+       // switch back to original stack and g
+       // no-op if we never left.
+       MOVQ    104(SP), SP
+       MOVQ    96(SP), DX
+       get_tls(BP)
+       MOVQ    DX, g(BP)
+
 done:
        // restore registers as required for windows callback
        MOVQ    88(SP), R15
@@ -147,7 +182,7 @@ done:
        MOVQ    64(SP), BP
        MOVQ    72(SP), SI
        MOVQ    80(SP), DI
-       ADDQ    $96, SP
+       ADDQ    $112, SP
        POPFQ
 
        RET