Commit 8bad008c authored by Clément Chigot's avatar Clément Chigot Committed by Ian Lance Taylor

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: default avatarIan Lance Taylor <iant@golang.org>
parent 340129e4
...@@ -148,32 +148,35 @@ type libFunc uintptr ...@@ -148,32 +148,35 @@ type libFunc uintptr
// It's defined in sys_aix_ppc64.go. // It's defined in sys_aix_ppc64.go.
var asmsyscall6 libFunc 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:nowritebarrier
//go:nosplit //go:nosplit
func syscall0(fn *libFunc) (r, err uintptr) { func syscall0(fn *libFunc) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } 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.fn = uintptr(unsafe.Pointer(fn))
c.n = 0 c.n = 0
c.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes c.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -184,18 +187,16 @@ func syscall0(fn *libFunc) (r, err uintptr) { ...@@ -184,18 +187,16 @@ func syscall0(fn *libFunc) (r, err uintptr) {
//go:nosplit //go:nosplit
func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) { func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } else {
mp = nil // See comment in sys_darwin.go:libcCall resetLibcall = false // See comment in sys_darwin.go:libcCall
} }
c := &gp.m.libcall c := &gp.m.libcall
...@@ -205,7 +206,7 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) { ...@@ -205,7 +206,7 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -216,18 +217,16 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) { ...@@ -216,18 +217,16 @@ func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
//go:nosplit //go:nosplit
func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) { func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } else {
mp = nil // See comment in sys_darwin.go:libcCall resetLibcall = false // See comment in sys_darwin.go:libcCall
} }
c := &gp.m.libcall c := &gp.m.libcall
...@@ -237,7 +236,7 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) { ...@@ -237,7 +236,7 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -248,18 +247,16 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) { ...@@ -248,18 +247,16 @@ func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
//go:nosplit //go:nosplit
func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) { func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } else {
mp = nil // See comment in sys_darwin.go:libcCall resetLibcall = false // See comment in sys_darwin.go:libcCall
} }
c := &gp.m.libcall c := &gp.m.libcall
...@@ -269,7 +266,7 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) { ...@@ -269,7 +266,7 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -280,18 +277,16 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) { ...@@ -280,18 +277,16 @@ func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
//go:nosplit //go:nosplit
func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) { func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } else {
mp = nil // See comment in sys_darwin.go:libcCall resetLibcall = false // See comment in sys_darwin.go:libcCall
} }
c := &gp.m.libcall c := &gp.m.libcall
...@@ -301,7 +296,7 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) { ...@@ -301,7 +296,7 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -312,18 +307,16 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) { ...@@ -312,18 +307,16 @@ func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
//go:nosplit //go:nosplit
func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) { func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } else {
mp = nil // See comment in sys_darwin.go:libcCall resetLibcall = false // See comment in sys_darwin.go:libcCall
} }
c := &gp.m.libcall c := &gp.m.libcall
...@@ -333,7 +326,7 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) { ...@@ -333,7 +326,7 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -344,18 +337,16 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) { ...@@ -344,18 +337,16 @@ func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
//go:nosplit //go:nosplit
func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) { func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
gp := getg() gp := getg()
var mp *m mp := gp.m
if gp != nil { resetLibcall := true
mp = gp.m if mp.libcallsp == 0 {
}
if mp != nil && mp.libcallsp == 0 {
mp.libcallg.set(gp) mp.libcallg.set(gp)
mp.libcallpc = getcallerpc() mp.libcallpc = getcallerpc()
// sp must be the last, because once async cpu profiler finds // sp must be the last, because once async cpu profiler finds
// all three values to be non-zero, it will use them // all three values to be non-zero, it will use them
mp.libcallsp = getcallersp() mp.libcallsp = getcallersp()
} else { } else {
mp = nil // See comment in sys_darwin.go:libcCall resetLibcall = false // See comment in sys_darwin.go:libcCall
} }
c := &gp.m.libcall c := &gp.m.libcall
...@@ -365,7 +356,7 @@ func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) { ...@@ -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)) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
if mp != nil { if resetLibcall {
mp.libcallsp = 0 mp.libcallsp = 0
} }
...@@ -461,13 +452,23 @@ func getsystemcfg(label uint) uintptr { ...@@ -461,13 +452,23 @@ func getsystemcfg(label uint) uintptr {
return r return r
} }
func usleep1(us uint32)
//go:nosplit //go:nosplit
func usleep(us uint32) { func usleep(us uint32) {
r, err := syscall1(&libc_usleep, uintptr(us)) _g_ := getg()
if int32(r) == -1 {
println("syscall usleep failed: ", hex(err)) // Check the validity of m because we might be called in cgo callback
throw("syscall usleep") // 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 //go:nosplit
...@@ -541,8 +542,8 @@ func osyield1() ...@@ -541,8 +542,8 @@ func osyield1()
func osyield() { func osyield() {
_g_ := getg() _g_ := getg()
// Check the validity of m because we might be called in cgo callback // Check the validity of m because it might be called during a cgo
// path early enough where there isn't a m available yet. // callback early enough where m isn't available yet.
if _g_ != nil && _g_.m != nil { if _g_ != nil && _g_.m != nil {
r, err := syscall0(&libc_sched_yield) r, err := syscall0(&libc_sched_yield)
if int32(r) == -1 { if int32(r) == -1 {
...@@ -611,11 +612,22 @@ func pthread_create(tid *pthread, attr *pthread_attr, fn *funcDescriptor, arg un ...@@ -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. // On multi-thread program, sigprocmask must not be called.
// It's replaced by sigthreadmask. // It's replaced by sigthreadmask.
func sigprocmask1(how, new, old uintptr)
//go:nosplit //go:nosplit
func sigprocmask(how int32, new, old *sigset) { func sigprocmask(how int32, new, old *sigset) {
r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old))) _g_ := getg()
if int32(r) != 0 {
println("syscall sigthreadmask failed: ", hex(err)) // Check the validity of m because it might be called during a cgo
throw("syscall sigthreadmask") // 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)))
} }
...@@ -204,4 +204,36 @@ TEXT runtime·osyield1(SB),NOSPLIT,$0 ...@@ -204,4 +204,36 @@ TEXT runtime·osyield1(SB),NOSPLIT,$0
MOVD R0, CTR MOVD R0, CTR
BL (CTR) BL (CTR)
MOVD 40(R1), R2 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 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