1
0
mirror of https://github.com/golang/go synced 2024-09-25 07:20:12 -06:00

runtime: handle syscalls without g or m for aix/ppc64

With cgo, some syscalls will be called with g == nil or m == nil.
SyscallX functions cannot handle them so they call an equivalent
function in sys_aix_ppc64.s which will directly call this syscall.

Change-Id: I6508ec772b304111330e6833e7db729200af547c
Reviewed-on: https://go-review.googlesource.com/c/go/+/164001
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Clément Chigot 2019-02-20 16:01:22 +01:00 committed by Ian Lance Taylor
parent 340129e4c8
commit 8bad008cf5
2 changed files with 104 additions and 60 deletions

View File

@ -148,32 +148,35 @@ type libFunc uintptr
// It's defined in sys_aix_ppc64.go.
var asmsyscall6 libFunc
// syscallX functions must always be called with g != nil and m != nil,
// as it relies on g.m.libcall to pass arguments to asmcgocall.
// The few cases where syscalls haven't a g or a m must call their equivalent
// function in sys_aix_ppc64.s to handle them.
//go:nowritebarrier
//go:nosplit
func syscall0(fn *libFunc) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
c := &mp.libcall
c.fn = uintptr(unsafe.Pointer(fn))
c.n = 0
c.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -184,18 +187,16 @@ func syscall0(fn *libFunc) (r, err uintptr) {
//go:nosplit
func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
@ -205,7 +206,7 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -216,18 +217,16 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
//go:nosplit
func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
@ -237,7 +236,7 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -248,18 +247,16 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
//go:nosplit
func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
@ -269,7 +266,7 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -280,18 +277,16 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
//go:nosplit
func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
@ -301,7 +296,7 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -312,18 +307,16 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
//go:nosplit
func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
@ -333,7 +326,7 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -344,18 +337,16 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
//go:nosplit
func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
gp := getg()
var mp *m
if gp != nil {
mp = gp.m
}
if mp != nil && mp.libcallsp == 0 {
mp := gp.m
resetLibcall := true
if mp.libcallsp == 0 {
mp.libcallg.set(gp)
mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them
mp.libcallsp = getcallersp()
} else {
mp = nil // See comment in sys_darwin.go:libcCall
resetLibcall = false // See comment in sys_darwin.go:libcCall
}
c := &gp.m.libcall
@ -365,7 +356,7 @@ func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil {
if resetLibcall {
mp.libcallsp = 0
}
@ -461,13 +452,23 @@ func getsystemcfg(label uint) uintptr {
return r
}
func usleep1(us uint32)
//go:nosplit
func usleep(us uint32) {
r, err := syscall1(&libc_usleep, uintptr(us))
if int32(r) == -1 {
println("syscall usleep failed: ", hex(err))
throw("syscall usleep")
_g_ := getg()
// Check the validity of m because we might be called in cgo callback
// path early enough where there isn't a g or a m available yet.
if _g_ != nil && _g_.m != nil {
r, err := syscall1(&libc_usleep, uintptr(us))
if int32(r) == -1 {
println("syscall usleep failed: ", hex(err))
throw("syscall usleep")
}
return
}
usleep1(us)
}
//go:nosplit
@ -541,8 +542,8 @@ func osyield1()
func osyield() {
_g_ := getg()
// Check the validity of m because we might be called in cgo callback
// path early enough where there isn't a m available yet.
// Check the validity of m because it might be called during a cgo
// callback early enough where m isn't available yet.
if _g_ != nil && _g_.m != nil {
r, err := syscall0(&libc_sched_yield)
if int32(r) == -1 {
@ -611,11 +612,22 @@ func pthread_create(tid *pthread, attr *pthread_attr, fn *funcDescriptor, arg un
// On multi-thread program, sigprocmask must not be called.
// It's replaced by sigthreadmask.
func sigprocmask1(how, new, old uintptr)
//go:nosplit
func sigprocmask(how int32, new, old *sigset) {
r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
if int32(r) != 0 {
println("syscall sigthreadmask failed: ", hex(err))
throw("syscall sigthreadmask")
_g_ := getg()
// Check the validity of m because it might be called during a cgo
// callback early enough where m isn't available yet.
if _g_ != nil && _g_.m != nil {
r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
if int32(r) != 0 {
println("syscall sigthreadmask failed: ", hex(err))
throw("syscall sigthreadmask")
}
return
}
sigprocmask1(uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
}

View File

@ -204,4 +204,36 @@ TEXT runtime·osyield1(SB),NOSPLIT,$0
MOVD R0, CTR
BL (CTR)
MOVD 40(R1), R2
BL runtime·reginit(SB)
RET
// Runs on OS stack, called from runtime·sigprocmask.
TEXT runtime·sigprocmask1(SB),NOSPLIT,$0-24
MOVD how+0(FP), R3
MOVD new+8(FP), R4
MOVD old+16(FP), R5
MOVD $libpthread_sigthreadmask(SB), R12
MOVD 0(R12), R12
MOVD R2, 40(R1)
MOVD 0(R12), R0
MOVD 8(R12), R2
MOVD R0, CTR
BL (CTR)
MOVD 40(R1), R2
BL runtime·reginit(SB)
RET
// Runs on OS stack, called from runtime·usleep.
TEXT runtime·usleep1(SB),NOSPLIT,$0-8
MOVW us+0(FP), R3
MOVD $libc_usleep(SB), R12
MOVD 0(R12), R12
MOVD R2, 40(R1)
MOVD 0(R12), R0
MOVD 8(R12), R2
MOVD R0, CTR
BL (CTR)
MOVD 40(R1), R2
BL runtime·reginit(SB)
RET