Commit 201cfe4a authored by Russ Cox's avatar Russ Cox

runtime: run sighandler on g0 stack on windows

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
parent 3a3d47db
...@@ -76,7 +76,7 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0 ...@@ -76,7 +76,7 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0
// Return 0 for 'not handled', -1 for handled. // Return 0 for 'not handled', -1 for handled.
TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
MOVL ptrs+0(FP), CX MOVL ptrs+0(FP), CX
SUBL $32, SP SUBL $40, SP
// save callee-saved registers // save callee-saved registers
MOVL BX, 28(SP) MOVL BX, 28(SP)
...@@ -84,10 +84,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -84,10 +84,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
MOVL SI, 20(SP) MOVL SI, 20(SP)
MOVL DI, 24(SP) MOVL DI, 24(SP)
MOVL 0(CX), BX // ExceptionRecord* // find g
MOVL 4(CX), CX // Context*
// fetch g
get_tls(DX) get_tls(DX)
CMPL DX, $0 CMPL DX, $0
JNE 3(PC) JNE 3(PC)
...@@ -97,6 +94,35 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -97,6 +94,35 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
CMPL DX, $0 CMPL DX, $0
JNE 2(PC) JNE 2(PC)
CALL runtime·badsignal2(SB) 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*) // call sighandler(ExceptionRecord*, Context*, G*)
MOVL BX, 0(SP) MOVL BX, 0(SP)
MOVL CX, 4(SP) MOVL CX, 4(SP)
...@@ -105,6 +131,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -105,6 +131,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
// AX is set to report result back to Windows // AX is set to report result back to Windows
MOVL 12(SP), AX 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: done:
// restore callee-saved registers // restore callee-saved registers
MOVL 24(SP), DI MOVL 24(SP), DI
...@@ -112,7 +145,7 @@ done: ...@@ -112,7 +145,7 @@ done:
MOVL 16(SP), BP MOVL 16(SP), BP
MOVL 28(SP), BX MOVL 28(SP), BX
ADDL $32, SP ADDL $40, SP
// RET 4 (return and pop 4 bytes parameters) // RET 4 (return and pop 4 bytes parameters)
BYTE $0xC2; WORD $4 BYTE $0xC2; WORD $4
RET // unreached; make assembler happy RET // unreached; make assembler happy
...@@ -128,7 +161,7 @@ TEXT runtime·profileloop(SB),NOSPLIT,$0 ...@@ -128,7 +161,7 @@ TEXT runtime·profileloop(SB),NOSPLIT,$0
PUSHL $runtime·profileloop1(SB) PUSHL $runtime·profileloop1(SB)
CALL runtime·externalthreadhandler(SB) CALL runtime·externalthreadhandler(SB)
MOVL 4(SP), CX MOVL 4(SP), CX
ADDL $12, SP ADDL $40, SP
JMP CX JMP CX
TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
......
...@@ -106,7 +106,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -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 // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
// as required by windows callback convention. // as required by windows callback convention.
PUSHFQ PUSHFQ
SUBQ $96, SP SUBQ $112, SP
MOVQ DI, 80(SP) MOVQ DI, 80(SP)
MOVQ SI, 72(SP) MOVQ SI, 72(SP)
MOVQ BP, 64(SP) MOVQ BP, 64(SP)
...@@ -116,10 +116,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -116,10 +116,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
MOVQ R14, 32(SP) MOVQ R14, 32(SP)
MOVQ R15, 88(SP) MOVQ R15, 88(SP)
MOVQ 0(CX), BX // ExceptionRecord* // find g
MOVQ 8(CX), CX // Context*
// fetch g
get_tls(DX) get_tls(DX)
CMPQ DX, $0 CMPQ DX, $0
JNE 3(PC) JNE 3(PC)
...@@ -129,6 +126,37 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -129,6 +126,37 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
CMPQ DX, $0 CMPQ DX, $0
JNE 2(PC) JNE 2(PC)
CALL runtime·badsignal2(SB) 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*) // call sighandler(ExceptionRecord*, Context*, G*)
MOVQ BX, 0(SP) MOVQ BX, 0(SP)
MOVQ CX, 8(SP) MOVQ CX, 8(SP)
...@@ -137,6 +165,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 ...@@ -137,6 +165,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
// AX is set to report result back to Windows // AX is set to report result back to Windows
MOVL 24(SP), AX 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: done:
// restore registers as required for windows callback // restore registers as required for windows callback
MOVQ 88(SP), R15 MOVQ 88(SP), R15
...@@ -147,7 +182,7 @@ done: ...@@ -147,7 +182,7 @@ done:
MOVQ 64(SP), BP MOVQ 64(SP), BP
MOVQ 72(SP), SI MOVQ 72(SP), SI
MOVQ 80(SP), DI MOVQ 80(SP), DI
ADDQ $96, SP ADDQ $112, SP
POPFQ POPFQ
RET RET
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment