]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix backtrace during C syscalls for aix/ppc64
authorClément Chigot <clement.chigot@atos.net>
Tue, 18 Dec 2018 12:00:26 +0000 (13:00 +0100)
committerIan Lance Taylor <iant@golang.org>
Tue, 18 Dec 2018 15:43:50 +0000 (15:43 +0000)
This commit fixes backtrace if a crash or an exit signal is received
during a C syscall on aix/ppc64.
This is similar to Solaris, Darwin or Windows implementation.

Change-Id: I6040c0b1577a9f5b298f58bd4ee6556258a135ef
Reviewed-on: https://go-review.googlesource.com/c/154718
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

index c478d4b0d89b257d0cf833849256b53f8df57f5b..d0349191c6d307b00758e5bb89a89f8d63d8e389 100644 (file)
@@ -151,91 +151,224 @@ var asmsyscall6 libFunc
 //go:nowritebarrier
 //go:nosplit
 func syscall0(fn *libFunc) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.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 {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }
 
 //go:nowritebarrier
 //go:nosplit
 func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.libcall
        c.fn = uintptr(unsafe.Pointer(fn))
        c.n = 1
        c.args = uintptr(noescape(unsafe.Pointer(&a0)))
 
        asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
 
+       if mp != nil {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }
 
 //go:nowritebarrier
 //go:nosplit
 func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.libcall
        c.fn = uintptr(unsafe.Pointer(fn))
        c.n = 2
        c.args = uintptr(noescape(unsafe.Pointer(&a0)))
 
        asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
 
+       if mp != nil {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }
 
 //go:nowritebarrier
 //go:nosplit
 func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.libcall
        c.fn = uintptr(unsafe.Pointer(fn))
        c.n = 3
        c.args = uintptr(noescape(unsafe.Pointer(&a0)))
 
        asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
 
+       if mp != nil {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }
 
 //go:nowritebarrier
 //go:nosplit
 func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.libcall
        c.fn = uintptr(unsafe.Pointer(fn))
        c.n = 4
        c.args = uintptr(noescape(unsafe.Pointer(&a0)))
 
        asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
 
+       if mp != nil {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }
 
 //go:nowritebarrier
 //go:nosplit
 func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.libcall
        c.fn = uintptr(unsafe.Pointer(fn))
        c.n = 5
        c.args = uintptr(noescape(unsafe.Pointer(&a0)))
 
        asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
 
+       if mp != nil {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }
 
 //go:nowritebarrier
 //go:nosplit
 func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
-       c := &getg().m.libcall
+       gp := getg()
+       var mp *m
+       if gp != nil {
+               mp = gp.m
+       }
+       if mp != nil && 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
+       }
+
+       c := &gp.m.libcall
        c.fn = uintptr(unsafe.Pointer(fn))
        c.n = 6
        c.args = uintptr(noescape(unsafe.Pointer(&a0)))
 
        asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
 
+       if mp != nil {
+               mp.libcallsp = 0
+       }
+
        return c.r1, c.err
 }