aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorClément Chigot <clement.chigot@atos.net>2019-02-20 16:01:22 +0100
committerIan Lance Taylor <iant@golang.org>2019-03-05 20:55:00 +0000
commit8bad008cf50e64a7615d9dbd7aaa236eb727301e (patch)
treec11ec895d00f45833a3b6e187a4844a2ddee0feb /src/runtime
parent340129e4c8c56a371859b7434de89478610cab81 (diff)
downloadgo-8bad008cf50e64a7615d9dbd7aaa236eb727301e.tar.xz
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>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/os2_aix.go132
-rw-r--r--src/runtime/sys_aix_ppc64.s32
2 files changed, 104 insertions, 60 deletions
diff --git a/src/runtime/os2_aix.go b/src/runtime/os2_aix.go
index d0349191c6..e2ae04a55d 100644
--- a/src/runtime/os2_aix.go
+++ b/src/runtime/os2_aix.go
@@ -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)))
+
}
diff --git a/src/runtime/sys_aix_ppc64.s b/src/runtime/sys_aix_ppc64.s
index ea7fae0ce7..d691b76cc7 100644
--- a/src/runtime/sys_aix_ppc64.s
+++ b/src/runtime/sys_aix_ppc64.s
@@ -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