mirror of
https://github.com/golang/go
synced 2024-11-22 16:25:07 -07:00
runtime: eliminate externalthreadhandler
This function is no longer used. Eliminating this actually fixes several problems: - It made assumptions about what registers memclrNoHeapPointers would preserve. Besides being an abstraction violation and lurking maintenance issue, this actively became a problem for regabi because the call to memclrNoHeapPointers now happens through an ABI wrapper, which is generated by the compiler and hence we can't easily control what registers it clobbers. - The amd64 implementation (at least), does not interact with the host ABI correctly. Notably, it doesn't save many of the registers that are callee-save in the host ABI but caller-save in the Go ABI. - It interacts strangely with the NOSPLIT checker because it allocates an entire M and G on its stack. It worked around this on arm64, and happened to do things the NOSPLIT checker couldn't track on 386 and amd64, and happened to be *4 bytes* below the limit on arm (so any addition to the m or g structs would cause a NOSPLIT failure). See CL 309031 for a more complete explanation. Fixes #45530. Updates #40724. Change-Id: Ic70d4d7e1c17f1d796575b3377b8529449e93576 Reviewed-on: https://go-review.googlesource.com/c/go/+/309634 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
e69f02265c
commit
c19759aa48
@ -29,7 +29,6 @@ const (
|
||||
FuncID_asyncPreempt
|
||||
FuncID_cgocallback
|
||||
FuncID_debugCallV1
|
||||
FuncID_externalthreadhandler
|
||||
FuncID_gcBgMarkWorker
|
||||
FuncID_goexit
|
||||
FuncID_gogo
|
||||
@ -50,28 +49,27 @@ const (
|
||||
)
|
||||
|
||||
var funcIDs = map[string]FuncID{
|
||||
"abort": FuncID_abort,
|
||||
"asmcgocall": FuncID_asmcgocall,
|
||||
"asyncPreempt": FuncID_asyncPreempt,
|
||||
"cgocallback": FuncID_cgocallback,
|
||||
"debugCallV1": FuncID_debugCallV1,
|
||||
"externalthreadhandler": FuncID_externalthreadhandler,
|
||||
"gcBgMarkWorker": FuncID_gcBgMarkWorker,
|
||||
"go": FuncID_rt0_go,
|
||||
"goexit": FuncID_goexit,
|
||||
"gogo": FuncID_gogo,
|
||||
"gopanic": FuncID_gopanic,
|
||||
"handleAsyncEvent": FuncID_handleAsyncEvent,
|
||||
"jmpdefer": FuncID_jmpdefer,
|
||||
"main": FuncID_runtime_main,
|
||||
"mcall": FuncID_mcall,
|
||||
"morestack": FuncID_morestack,
|
||||
"mstart": FuncID_mstart,
|
||||
"panicwrap": FuncID_panicwrap,
|
||||
"runfinq": FuncID_runfinq,
|
||||
"sigpanic": FuncID_sigpanic,
|
||||
"switch": FuncID_systemstack_switch,
|
||||
"systemstack": FuncID_systemstack,
|
||||
"abort": FuncID_abort,
|
||||
"asmcgocall": FuncID_asmcgocall,
|
||||
"asyncPreempt": FuncID_asyncPreempt,
|
||||
"cgocallback": FuncID_cgocallback,
|
||||
"debugCallV1": FuncID_debugCallV1,
|
||||
"gcBgMarkWorker": FuncID_gcBgMarkWorker,
|
||||
"go": FuncID_rt0_go,
|
||||
"goexit": FuncID_goexit,
|
||||
"gogo": FuncID_gogo,
|
||||
"gopanic": FuncID_gopanic,
|
||||
"handleAsyncEvent": FuncID_handleAsyncEvent,
|
||||
"jmpdefer": FuncID_jmpdefer,
|
||||
"main": FuncID_runtime_main,
|
||||
"mcall": FuncID_mcall,
|
||||
"morestack": FuncID_morestack,
|
||||
"mstart": FuncID_mstart,
|
||||
"panicwrap": FuncID_panicwrap,
|
||||
"runfinq": FuncID_runfinq,
|
||||
"sigpanic": FuncID_sigpanic,
|
||||
"switch": FuncID_systemstack_switch,
|
||||
"systemstack": FuncID_systemstack,
|
||||
|
||||
// Don't show in call stack but otherwise not special.
|
||||
"deferreturn": FuncID_wrapper,
|
||||
|
@ -947,9 +947,7 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
|
||||
// calls that may need more stack than we think.
|
||||
//
|
||||
// The default stack reserve size directly affects only the main
|
||||
// thread and threads that enter in externalthreadhandler.
|
||||
// For this, it must be greater than the stack size assumed by
|
||||
// externalthreadhandler.
|
||||
// thread.
|
||||
//
|
||||
// For other threads, the runtime explicitly asks the kernel
|
||||
// to use the default stack size so that all stacks are
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
|
||||
|
||||
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||
|
||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
|
||||
|
||||
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||
|
||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
@ -386,7 +386,6 @@ const (
|
||||
)
|
||||
|
||||
// in sys_windows_386.s and sys_windows_amd64.s:
|
||||
func externalthreadhandler()
|
||||
func getlasterror() uint32
|
||||
|
||||
// When loading DLLs, we prefer to use LoadLibraryEx with
|
||||
|
@ -317,7 +317,6 @@ const (
|
||||
funcID_asyncPreempt
|
||||
funcID_cgocallback
|
||||
funcID_debugCallV1
|
||||
funcID_externalthreadhandler
|
||||
funcID_gcBgMarkWorker
|
||||
funcID_goexit
|
||||
funcID_gogo
|
||||
|
@ -156,57 +156,6 @@ TEXT runtime·lastcontinuetramp<ABIInternal>(SB),NOSPLIT,$0-0
|
||||
MOVL $runtime·lastcontinuehandler(SB), AX
|
||||
JMP sigtramp<>(SB)
|
||||
|
||||
TEXT runtime·externalthreadhandler<ABIInternal>(SB),NOSPLIT|TOPFRAME,$0
|
||||
PUSHL BP
|
||||
MOVL SP, BP
|
||||
PUSHL BX
|
||||
PUSHL SI
|
||||
PUSHL DI
|
||||
PUSHL 0x14(FS)
|
||||
MOVL SP, DX
|
||||
|
||||
// setup dummy m, g
|
||||
SUBL $m__size, SP // space for M
|
||||
MOVL SP, 0(SP)
|
||||
MOVL $m__size, 4(SP)
|
||||
CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX
|
||||
|
||||
LEAL m_tls(SP), CX
|
||||
MOVL CX, 0x14(FS)
|
||||
MOVL SP, BX
|
||||
SUBL $g__size, SP // space for G
|
||||
MOVL SP, g(CX)
|
||||
MOVL SP, m_g0(BX)
|
||||
|
||||
MOVL SP, 0(SP)
|
||||
MOVL $g__size, 4(SP)
|
||||
CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX
|
||||
LEAL g__size(SP), BX
|
||||
MOVL BX, g_m(SP)
|
||||
|
||||
LEAL -32768(SP), CX // must be less than SizeOfStackReserve set by linker
|
||||
MOVL CX, (g_stack+stack_lo)(SP)
|
||||
ADDL $const__StackGuard, CX
|
||||
MOVL CX, g_stackguard0(SP)
|
||||
MOVL CX, g_stackguard1(SP)
|
||||
MOVL DX, (g_stack+stack_hi)(SP)
|
||||
|
||||
PUSHL AX // room for return value
|
||||
PUSHL 16(BP) // arg for handler
|
||||
CALL 8(BP)
|
||||
POPL CX
|
||||
POPL AX // pass return value to Windows in AX
|
||||
|
||||
get_tls(CX)
|
||||
MOVL g(CX), CX
|
||||
MOVL (g_stack+stack_hi)(CX), SP
|
||||
POPL 0x14(FS)
|
||||
POPL DI
|
||||
POPL SI
|
||||
POPL BX
|
||||
POPL BP
|
||||
RET
|
||||
|
||||
GLOBL runtime·cbctxts(SB), NOPTR, $4
|
||||
|
||||
TEXT runtime·callbackasm1<ABIInternal>(SB),NOSPLIT,$0
|
||||
|
@ -202,57 +202,6 @@ TEXT runtime·lastcontinuetramp<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MOVQ $runtime·lastcontinuehandler(SB), AX
|
||||
JMP sigtramp<>(SB)
|
||||
|
||||
TEXT runtime·externalthreadhandler<ABIInternal>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
|
||||
PUSHQ BP
|
||||
MOVQ SP, BP
|
||||
PUSHQ BX
|
||||
PUSHQ SI
|
||||
PUSHQ DI
|
||||
PUSHQ 0x28(GS)
|
||||
MOVQ SP, DX
|
||||
|
||||
// setup dummy m, g
|
||||
SUBQ $m__size, SP // space for M
|
||||
MOVQ SP, 0(SP)
|
||||
MOVQ $m__size, 8(SP)
|
||||
CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX, maybe BP
|
||||
|
||||
LEAQ m_tls(SP), CX
|
||||
MOVQ CX, 0x28(GS)
|
||||
MOVQ SP, BX
|
||||
SUBQ $g__size, SP // space for G
|
||||
MOVQ SP, g(CX)
|
||||
MOVQ SP, m_g0(BX)
|
||||
|
||||
MOVQ SP, 0(SP)
|
||||
MOVQ $g__size, 8(SP)
|
||||
CALL runtime·memclrNoHeapPointers(SB) // smashes AX,BX,CX, maybe BP
|
||||
LEAQ g__size(SP), BX
|
||||
MOVQ BX, g_m(SP)
|
||||
|
||||
LEAQ -32768(SP), CX // must be less than SizeOfStackReserve set by linker
|
||||
MOVQ CX, (g_stack+stack_lo)(SP)
|
||||
ADDQ $const__StackGuard, CX
|
||||
MOVQ CX, g_stackguard0(SP)
|
||||
MOVQ CX, g_stackguard1(SP)
|
||||
MOVQ DX, (g_stack+stack_hi)(SP)
|
||||
|
||||
PUSHQ AX // room for return value
|
||||
PUSHQ 32(BP) // arg for handler
|
||||
CALL 16(BP)
|
||||
POPQ CX
|
||||
POPQ AX // pass return value to Windows in AX
|
||||
|
||||
get_tls(CX)
|
||||
MOVQ g(CX), CX
|
||||
MOVQ (g_stack+stack_hi)(CX), SP
|
||||
POPQ 0x28(GS)
|
||||
POPQ DI
|
||||
POPQ SI
|
||||
POPQ BX
|
||||
POPQ BP
|
||||
RET
|
||||
|
||||
GLOBL runtime·cbctxts(SB), NOPTR, $8
|
||||
|
||||
TEXT runtime·callbackasm1(SB),NOSPLIT,$0
|
||||
|
@ -233,73 +233,6 @@ TEXT runtime·lastcontinuetramp<ABIInternal>(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW $runtime·lastcontinuehandler(SB), R1
|
||||
B sigtramp<>(SB)
|
||||
|
||||
// int32 externalthreadhandler(uint32 arg, int (*func)(uint32))
|
||||
// stack layout:
|
||||
// +----------------+
|
||||
// | callee-save |
|
||||
// | registers |
|
||||
// +----------------+
|
||||
// | m |
|
||||
// +----------------+
|
||||
// 20| g |
|
||||
// +----------------+
|
||||
// 16| func ptr (r1) |
|
||||
// +----------------+
|
||||
// 12| argument (r0) |
|
||||
//---+----------------+
|
||||
// 8 | param1 | (also return value for called Go function)
|
||||
// +----------------+
|
||||
// 4 | param0 |
|
||||
// +----------------+
|
||||
// 0 | slot for LR |
|
||||
// +----------------+
|
||||
//
|
||||
TEXT runtime·externalthreadhandler<ABIInternal>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
|
||||
MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr}
|
||||
SUB $(m__size + g__size + 20), R13 // space for locals
|
||||
MOVW R14, 0(R13) // push LR again for anything unwinding the stack
|
||||
MOVW R0, 12(R13)
|
||||
MOVW R1, 16(R13)
|
||||
|
||||
// zero out m and g structures
|
||||
ADD $20, R13, R0 // compute pointer to g
|
||||
MOVW R0, 4(R13)
|
||||
MOVW $(m__size + g__size), R0
|
||||
MOVW R0, 8(R13)
|
||||
BL runtime·memclrNoHeapPointers(SB)
|
||||
|
||||
// initialize m and g structures
|
||||
ADD $20, R13, R2 // R2 = g
|
||||
ADD $(20 + g__size), R13, R3 // R3 = m
|
||||
MOVW R2, m_g0(R3) // m->g0 = g
|
||||
MOVW R3, g_m(R2) // g->m = m
|
||||
MOVW R2, m_curg(R3) // m->curg = g
|
||||
|
||||
MOVW R2, g
|
||||
BL runtime·save_g(SB)
|
||||
|
||||
// set up stackguard stuff
|
||||
MOVW R13, R0
|
||||
MOVW R0, g_stack+stack_hi(g)
|
||||
SUB $(32*1024), R0
|
||||
MOVW R0, (g_stack+stack_lo)(g)
|
||||
MOVW R0, g_stackguard0(g)
|
||||
MOVW R0, g_stackguard1(g)
|
||||
|
||||
// move argument into position and call function
|
||||
MOVW 12(R13), R0
|
||||
MOVW R0, 4(R13)
|
||||
MOVW 16(R13), R1
|
||||
BL (R1)
|
||||
|
||||
// clear g
|
||||
MOVW $0, g
|
||||
BL runtime·save_g(SB)
|
||||
|
||||
MOVW 8(R13), R0 // load return value
|
||||
ADD $(m__size + g__size + 20), R13 // free locals
|
||||
MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc}
|
||||
|
||||
GLOBL runtime·cbctxts(SB), NOPTR, $4
|
||||
|
||||
TEXT runtime·callbackasm1<ABIInternal>(SB),NOSPLIT|NOFRAME,$0
|
||||
|
@ -299,66 +299,6 @@ TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVD $runtime·lastcontinuehandler<ABIInternal>(SB), R1
|
||||
B sigtramp<>(SB)
|
||||
|
||||
// externalthreadhander called with R0 = uint32 arg, R1 = Go function f.
|
||||
// Need to call f(arg), which returns a uint32, and return it in R0.
|
||||
TEXT runtime·externalthreadhandler<ABIInternal>(SB),NOSPLIT|TOPFRAME,$96-0
|
||||
NO_LOCAL_POINTERS
|
||||
|
||||
// Push C callee-save registers R19-R28. LR, FP already saved.
|
||||
SAVE_R19_TO_R28(-10*8)
|
||||
|
||||
// Allocate space for args, saved R0+R1, g, and m structures.
|
||||
// Hide from nosplit check.
|
||||
#define extra ((64+g__size+m__size+15)&~15)
|
||||
SUB $extra, RSP, R2 // hide from nosplit overflow check
|
||||
MOVD R2, RSP
|
||||
|
||||
// Save R0 and R1 (our args).
|
||||
MOVD R0, 32(RSP)
|
||||
MOVD R1, 40(RSP)
|
||||
|
||||
// Zero out m and g structures.
|
||||
MOVD $64(RSP), R0
|
||||
MOVD R0, 8(RSP)
|
||||
MOVD $(m__size + g__size), R0
|
||||
MOVD R0, 16(RSP)
|
||||
MOVD $0, 0(RSP) // not-saved LR
|
||||
BL runtime·memclrNoHeapPointers(SB)
|
||||
|
||||
// Initialize m and g structures.
|
||||
MOVD $64(RSP), g
|
||||
MOVD $g__size(g), R3 // m
|
||||
MOVD R3, g_m(g) // g->m = m
|
||||
MOVD g, m_g0(R3) // m->g0 = g
|
||||
MOVD g, m_curg(R3) // m->curg = g
|
||||
MOVD RSP, R0
|
||||
MOVD R0, g_stack+stack_hi(g)
|
||||
SUB $(32*1024), R0
|
||||
MOVD R0, (g_stack+stack_lo)(g)
|
||||
MOVD R0, g_stackguard0(g)
|
||||
MOVD R0, g_stackguard1(g)
|
||||
BL runtime·save_g(SB)
|
||||
|
||||
// Call function.
|
||||
MOVD 32(RSP), R0
|
||||
MOVD 40(RSP), R1
|
||||
MOVW R0, 8(RSP)
|
||||
BL (R1)
|
||||
|
||||
// Clear g.
|
||||
MOVD $0, g
|
||||
BL runtime·save_g(SB)
|
||||
|
||||
// Load return value (save_g would have smashed)
|
||||
MOVW (2*8)(RSP), R0
|
||||
|
||||
ADD $extra, RSP, R2
|
||||
MOVD R2, RSP
|
||||
#undef extra
|
||||
|
||||
RESTORE_R19_TO_R28(-10*8)
|
||||
RET
|
||||
|
||||
GLOBL runtime·cbctxts(SB), NOPTR, $4
|
||||
|
||||
TEXT runtime·callbackasm1<ABIInternal>(SB),NOSPLIT,$208-0
|
||||
|
Loading…
Reference in New Issue
Block a user