mirror of
https://github.com/golang/go
synced 2024-11-19 12:34:47 -07:00
runtime: set libcall values for Solaris system calls
This lets SIGPROF signals get a useful traceback. Without it we just see sysvicallN calling asmcgocall. Updates #24142 Change-Id: I5dfe3add51f0c3a4cb1c98acb7738be6396214bc Reviewed-on: https://go-review.googlesource.com/99617 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
8e427a3878
commit
4902778607
@ -31,71 +31,190 @@ var asmsysvicall6 libcFunc
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall0(fn *libcFunc) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 0
|
||||
libcall.args = uintptr(unsafe.Pointer(fn)) // it's unused but must be non-nil, otherwise crashes
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 1
|
||||
// TODO(rsc): Why is noescape necessary here and below?
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 2
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 3
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 4
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 5
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
|
||||
// Leave caller's PC/SP around for traceback.
|
||||
gp := getg()
|
||||
var mp *m
|
||||
if gp != nil {
|
||||
mp = gp.m
|
||||
}
|
||||
if mp != nil {
|
||||
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(unsafe.Pointer(&fn))
|
||||
}
|
||||
|
||||
var libcall libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.n = 6
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
|
||||
if mp != nil {
|
||||
mp.libcallsp = 0
|
||||
}
|
||||
return libcall.r1
|
||||
}
|
||||
|
@ -3697,7 +3697,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
|
||||
// Normal traceback is impossible or has failed.
|
||||
// See if it falls into several common cases.
|
||||
n = 0
|
||||
if GOOS == "windows" && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
|
||||
if (GOOS == "windows" || GOOS == "solaris") && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
|
||||
// Libcall, i.e. runtime syscall on windows.
|
||||
// Collect Go stack that leads to the call.
|
||||
n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user