]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: handle syscalls without g or m for aix/ppc64
authorClément Chigot <clement.chigot@atos.net>
Wed, 20 Feb 2019 15:01:22 +0000 (16:01 +0100)
committerIan Lance Taylor <iant@golang.org>
Tue, 5 Mar 2019 20:55:00 +0000 (20:55 +0000)
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>
src/runtime/os2_aix.go
src/runtime/sys_aix_ppc64.s

index d0349191c6d307b00758e5bb89a89f8d63d8e389..e2ae04a55d3daae1d657f7cf81b15d59f8395041 100644 (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)))
+
 }
index ea7fae0ce78a5604d969940d640436a0f42531a0..d691b76cc7d7359bb833b559b581f54126cf8775 100644 (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