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:
parent
340129e4c8
commit
8bad008cf5
@ -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)))
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user