1
0
mirror of https://github.com/golang/go synced 2024-11-23 09:20:05 -07:00

runtime: M-targeted signals for BSDs

For these, we split up the existing runtime.raise assembly
implementation into its constituent "get thread ID" and "signal
thread" parts. This lets us implement signalM and reimplement raise in
pure Go. (NetBSD conveniently already had lwp_self.)

We also change minit to store the procid directly, rather than
depending on newosproc to do so. This is because newosproc isn't
called for the bootstrap M, but we need a procid for every M. This is
also simpler overall.

For #10958, #24543.

Change-Id: Ie5f1fcada6a33046375066bcbe054d1f784d39c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/201402
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Austin Clements 2019-10-14 17:05:56 -04:00
parent 334291d1f6
commit 8714e39497
21 changed files with 160 additions and 78 deletions

View File

@ -126,6 +126,8 @@ type thrparam struct {
spare [3]uintptr
}
type thread int32 // long
type sigset struct {
__bits [4]uint32
}

View File

@ -127,6 +127,8 @@ type thrparam struct {
spare [3]uintptr
}
type thread int64 // long
type sigset struct {
__bits [4]uint32
}

View File

@ -126,6 +126,8 @@ type thrparam struct {
spare [3]uintptr
}
type thread int32 // long
type sigset struct {
__bits [4]uint32
}

View File

@ -127,6 +127,8 @@ type thrparam struct {
spare [3]uintptr
}
type thread int64 // long
type sigset struct {
__bits [4]uint32
}

View File

@ -38,9 +38,11 @@ func setitimer(mode int32, new, old *itimerval)
//go:noescape
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func raise(sig uint32)
func raiseproc(sig uint32)
func lwp_gettid() int32
func lwp_kill(pid, tid int32, sig int)
//go:noescape
func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
@ -151,7 +153,7 @@ func newosproc(mp *m) {
start_func: funcPC(lwp_start),
arg: unsafe.Pointer(mp),
stack: uintptr(stk),
tid1: unsafe.Pointer(&mp.procid),
tid1: nil, // minit will record tid
tid2: nil,
}
@ -191,10 +193,7 @@ func mpreinit(mp *m) {
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, cannot allocate memory.
func minit() {
// m.procid is a uint64, but lwp_start writes an int32. Fix it up.
_g_ := getg()
_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
getg().m.procid = uint64(lwp_gettid())
minitSignals()
}
@ -288,3 +287,17 @@ func sysauxv(auxv []uintptr) {
}
}
}
// raise sends a signal to the calling thread.
//
// It must be nosplit because it is used by the signal handler before
// it definitely has a Go stack.
//
//go:nosplit
func raise(sig uint32) {
lwp_kill(-1, lwp_gettid(), int(sig))
}
func signalM(mp *m, sig int) {
lwp_kill(-1, int32(mp.procid), sig)
}

View File

@ -26,9 +26,11 @@ func setitimer(mode int32, new, old *itimerval)
//go:noescape
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func raise(sig uint32)
func raiseproc(sig uint32)
func thr_self() thread
func thr_kill(tid thread, sig int)
//go:noescape
func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32
@ -195,7 +197,7 @@ func newosproc(mp *m) {
arg: unsafe.Pointer(mp),
stack_base: mp.g0.stack.lo,
stack_size: uintptr(stk) - mp.g0.stack.lo,
child_tid: unsafe.Pointer(&mp.procid),
child_tid: nil, // minit will record tid
parent_tid: nil,
tls_base: unsafe.Pointer(&mp.tls[0]),
tls_size: unsafe.Sizeof(mp.tls),
@ -231,7 +233,7 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
arg: nil,
stack_base: uintptr(stack), //+stacksize?
stack_size: stacksize,
child_tid: unsafe.Pointer(&m0.procid),
child_tid: nil, // minit will record tid
parent_tid: nil,
tls_base: unsafe.Pointer(&m0.tls[0]),
tls_size: unsafe.Sizeof(m0.tls),
@ -290,12 +292,7 @@ func mpreinit(mp *m) {
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, cannot allocate memory.
func minit() {
// m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
// Fix it up. (Only matters on big-endian, but be clean anyway.)
if sys.PtrSize == 4 {
_g_ := getg()
_g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
}
getg().m.procid = uint64(thr_self())
// On FreeBSD before about April 2017 there was a bug such
// that calling execve from a thread other than the main
@ -423,3 +420,17 @@ func sysSigaction(sig uint32, new, old *sigactiont) {
// asmSigaction is implemented in assembly.
//go:noescape
func asmSigaction(sig uintptr, new, old *sigactiont) int32
// raise sends a signal to the calling thread.
//
// It must be nosplit because it is used by the signal handler before
// it definitely has a Go stack.
//
//go:nosplit
func raise(sig uint32) {
thr_kill(thr_self(), int(sig))
}
func signalM(mp *m, sig int) {
thr_kill(thread(mp.procid), sig)
}

View File

@ -47,9 +47,10 @@ func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, nds
func lwp_tramp()
func raise(sig uint32)
func raiseproc(sig uint32)
func lwp_kill(tid int32, sig int)
//go:noescape
func getcontext(ctxt unsafe.Pointer)
@ -361,3 +362,17 @@ func sysauxv(auxv []uintptr) {
}
}
}
// raise sends signal to the calling thread.
//
// It must be nosplit because it is used by the signal handler before
// it definitely has a Go stack.
//
//go:nosplit
func raise(sig uint32) {
lwp_kill(lwp_self(), int(sig))
}
func signalM(mp *m, sig int) {
lwp_kill(int32(mp.procid), sig)
}

View File

@ -42,9 +42,11 @@ func sigprocmask(how int32, new, old *sigset) {
//go:noescape
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func raise(sig uint32)
func raiseproc(sig uint32)
func getthrid() int32
func thrkill(tid int32, sig int)
//go:noescape
func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32
@ -190,7 +192,7 @@ func newosproc(mp *m) {
// rather than at the top of it.
param := tforkt{
tf_tcb: unsafe.Pointer(&mp.tls[0]),
tf_tid: (*int32)(unsafe.Pointer(&mp.procid)),
tf_tid: nil, // minit will record tid
tf_stack: uintptr(stk) - sys.PtrSize,
}
@ -238,10 +240,7 @@ func mpreinit(mp *m) {
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, can not allocate memory.
func minit() {
// m.procid is a uint64, but tfork writes an int32. Fix it up.
_g_ := getg()
_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
getg().m.procid = uint64(getthrid())
minitSignals()
}
@ -337,3 +336,11 @@ func osStackRemap(s *mspan, flags int32) {
throw("remapping stack memory failed")
}
}
func raise(sig uint32) {
thrkill(getthrid(), int(sig))
}
func signalM(mp *m, sig int) {
thrkill(int32(mp.procid), sig)
}

View File

@ -134,12 +134,16 @@ TEXT runtime·write1(SB),NOSPLIT,$-8
MOVL AX, ret+24(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
TEXT runtime·lwp_gettid(SB),NOSPLIT,$0-4
MOVL $496, AX // lwp_gettid
SYSCALL
MOVQ $-1, DI // arg 1 - pid
MOVQ AX, SI // arg 2 - tid
MOVL sig+0(FP), DX // arg 3 - signum
MOVL AX, ret+0(FP)
RET
TEXT runtime·lwp_kill(SB),NOSPLIT,$0-16
MOVL pid+0(FP), DI // arg 1 - pid
MOVL tid+4(FP), SI // arg 2 - tid
MOVQ sig+8(FP), DX // arg 3 - signum
MOVL $497, AX // lwp_kill
SYSCALL
RET

View File

@ -131,17 +131,16 @@ TEXT runtime·write1(SB),NOSPLIT,$-4
MOVL AX, ret+12(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
// thr_self(&8(SP))
LEAL 8(SP), AX
TEXT runtime·thr_self(SB),NOSPLIT,$8-4
// thr_self(&0(FP))
LEAL ret+0(FP), AX
MOVL AX, 4(SP)
MOVL $432, AX
INT $0x80
// thr_kill(self, SIGPIPE)
MOVL 8(SP), AX
MOVL AX, 4(SP)
MOVL sig+0(FP), AX
MOVL AX, 8(SP)
RET
TEXT runtime·thr_kill(SB),NOSPLIT,$-4
// thr_kill(tid, sig)
MOVL $433, AX
INT $0x80
RET

View File

@ -132,14 +132,17 @@ TEXT runtime·write1(SB),NOSPLIT,$-8
MOVL AX, ret+24(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$16
// thr_self(&8(SP))
LEAQ 8(SP), DI // arg 1 &8(SP)
TEXT runtime·thr_self(SB),NOSPLIT,$0-8
// thr_self(&0(FP))
LEAQ ret+0(FP), DI // arg 1
MOVL $432, AX
SYSCALL
// thr_kill(self, SIGPIPE)
MOVQ 8(SP), DI // arg 1 id
MOVL sig+0(FP), SI // arg 2
RET
TEXT runtime·thr_kill(SB),NOSPLIT,$0-16
// thr_kill(tid, sig)
MOVQ tid+0(FP), DI // arg 1 id
MOVQ sig+8(FP), SI // arg 2 sig
MOVL $433, AX
SYSCALL
RET

View File

@ -165,14 +165,17 @@ TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0
MOVW R0, ret+4(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$8
// thr_self(&4(R13))
MOVW $4(R13), R0 // arg 1 &4(R13)
TEXT runtime·thr_self(SB),NOSPLIT,$0-4
// thr_self(&0(FP))
MOVW $ret+0(FP), R0 // arg 1
MOVW $SYS_thr_self, R7
SWI $0
// thr_kill(self, SIGPIPE)
MOVW 4(R13), R0 // arg 1 id
MOVW sig+0(FP), R1 // arg 2 - signal
RET
TEXT runtime·thr_kill(SB),NOSPLIT,$0-8
// thr_kill(tid, sig)
MOVW tid+0(FP), R0 // arg 1 id
MOVW sig+4(FP), R1 // arg 2 signal
MOVW $SYS_thr_kill, R7
SWI $0
RET

View File

@ -197,13 +197,19 @@ TEXT runtime·usleep(SB),NOSPLIT,$24-4
SVC
RET
// func raise(sig uint32)
TEXT runtime·raise(SB),NOSPLIT,$8
MOVD $8(RSP), R0 // arg 1 &8(RSP)
// func thr_self() thread
TEXT runtime·thr_self(SB),NOSPLIT,$8-8
MOVD $ptr-8(SP), R0 // arg 1 &8(SP)
MOVD $SYS_thr_self, R8
SVC
MOVD 8(RSP), R0 // arg 1 pid
MOVW sig+0(FP), R1
MOVD ptr-8(SP), R0
MOVD R0, ret+0(FP)
RET
// func thr_kill(t thread, sig int)
TEXT runtime·thr_kill(SB),NOSPLIT,$0-16
MOVD tid+0(FP), R0 // arg 1 pid
MOVD sig+8(FP), R1 // arg 2 sig
MOVD $SYS_thr_kill, R8
SVC
RET

View File

@ -140,12 +140,11 @@ TEXT runtime·usleep(SB),NOSPLIT,$24
INT $0x80
RET
TEXT runtime·raise(SB),NOSPLIT,$12
MOVL $SYS__lwp_self, AX
INT $0x80
TEXT runtime·lwp_kill(SB),NOSPLIT,$12-8
MOVL $0, 0(SP)
MOVL tid+0(FP), AX
MOVL AX, 4(SP) // arg 1 - target
MOVL sig+0(FP), AX
MOVL sig+4(FP), AX
MOVL AX, 8(SP) // arg 2 - signo
MOVL $SYS__lwp_kill, AX
INT $0x80

View File

@ -209,11 +209,9 @@ TEXT runtime·usleep(SB),NOSPLIT,$16
SYSCALL
RET
TEXT runtime·raise(SB),NOSPLIT,$16
MOVL $SYS__lwp_self, AX
SYSCALL
MOVQ AX, DI // arg 1 - target
MOVL sig+0(FP), SI // arg 2 - signo
TEXT runtime·lwp_kill(SB),NOSPLIT,$0-16
MOVL tid+0(FP), DI // arg 1 - target
MOVQ sig+8(FP), SI // arg 2 - signo
MOVL $SYS__lwp_kill, AX
SYSCALL
RET

View File

@ -193,9 +193,9 @@ TEXT runtime·usleep(SB),NOSPLIT,$16
SWI $SYS___nanosleep50
RET
TEXT runtime·raise(SB),NOSPLIT,$16
SWI $SYS__lwp_self // the returned R0 is arg 1
MOVW sig+0(FP), R1 // arg 2 - signal
TEXT runtime·lwp_kill(SB),NOSPLIT,$0-8
MOVW tid+0(FP), R0 // arg 1 - tid
MOVW sig+4(FP), R1 // arg 2 - signal
SWI $SYS__lwp_kill
RET

View File

@ -205,10 +205,9 @@ TEXT runtime·usleep(SB),NOSPLIT,$24-4
SVC $SYS___nanosleep50
RET
TEXT runtime·raise(SB),NOSPLIT,$16
SVC $SYS__lwp_self
// arg 1 - target (lwp_self)
MOVW sig+0(FP), R1 // arg 2 - signo
TEXT runtime·lwp_kill(SB),NOSPLIT,$0-16
MOVW tid+0(FP), R0 // arg 1 - target
MOVD sig+8(FP), R1 // arg 2 - signo
SVC $SYS__lwp_kill
RET

View File

@ -97,12 +97,17 @@ TEXT runtime·usleep(SB),NOSPLIT,$24
INT $0x80
RET
TEXT runtime·raise(SB),NOSPLIT,$16
TEXT runtime·getthrid(SB),NOSPLIT,$0-4
MOVL $299, AX // sys_getthrid
INT $0x80
MOVL AX, ret+0(FP)
RET
TEXT runtime·thrkill(SB),NOSPLIT,$16-8
MOVL $0, 0(SP)
MOVL tid+0(FP), AX
MOVL AX, 4(SP) // arg 1 - tid
MOVL sig+0(FP), AX
MOVL sig+4(FP), AX
MOVL AX, 8(SP) // arg 2 - signum
MOVL $0, 12(SP) // arg 3 - tcb
MOVL $119, AX // sys_thrkill

View File

@ -171,11 +171,15 @@ TEXT runtime·usleep(SB),NOSPLIT,$16
SYSCALL
RET
TEXT runtime·raise(SB),NOSPLIT,$16
TEXT runtime·getthrid(SB),NOSPLIT,$0-4
MOVL $299, AX // sys_getthrid
SYSCALL
MOVQ AX, DI // arg 1 - tid
MOVL sig+0(FP), SI // arg 2 - signum
MOVL AX, ret+0(FP)
RET
TEXT runtime·thrkill(SB),NOSPLIT,$0-16
MOVL tid+0(FP), DI // arg 1 - tid
MOVQ sig+8(FP), SI // arg 2 - signum
MOVQ $0, DX // arg 3 - tcb
MOVL $119, AX // sys_thrkill
SYSCALL

View File

@ -102,11 +102,15 @@ TEXT runtime·usleep(SB),NOSPLIT,$16
SWI $0
RET
TEXT runtime·raise(SB),NOSPLIT,$12
TEXT runtime·getthrid(SB),NOSPLIT,$0-4
MOVW $299, R12 // sys_getthrid
SWI $0
// arg 1 - tid, already in R0
MOVW sig+0(FP), R1 // arg 2 - signum
MOVW R0, ret+0(FP)
RET
TEXT runtime·thrkill(SB),NOSPLIT,$0-8
MOVW tid+0(FP), R0 // arg 1 - tid
MOVW sig+4(FP), R1 // arg 2 - signum
MOVW $0, R2 // arg 3 - tcb
MOVW $119, R12 // sys_thrkill
SWI $0

View File

@ -114,11 +114,15 @@ TEXT runtime·usleep(SB),NOSPLIT,$24-4
SVC
RET
TEXT runtime·raise(SB),NOSPLIT,$0
TEXT runtime·getthrid(SB),NOSPLIT,$0-4
MOVD $299, R8 // sys_getthrid
SVC
// arg 1 - tid, already in R0
MOVW sig+0(FP), R1 // arg 2 - signum
MOVW R0, ret+0(FP)
RET
TEXT runtime·thrkill(SB),NOSPLIT,$0-16
MOVW tid+0(FP), R0 // arg 1 - tid
MOVD sig+8(FP), R1 // arg 2 - signum
MOVW $0, R2 // arg 3 - tcb
MOVD $119, R8 // sys_thrkill
SVC