mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: convert Stack to Go.
LGTM=khr R=khr, josharian CC=golang-codereviews https://golang.org/cl/129510043
This commit is contained in:
parent
0eaea6010a
commit
39ffa8be78
8 changed files with 72 additions and 39 deletions
|
|
@ -860,6 +860,12 @@ TEXT runtime·getcallersp(SB), NOSPLIT, $0-4
|
||||||
MOVL sp+0(FP), AX
|
MOVL sp+0(FP), AX
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// func gogetcallersp(p unsafe.Pointer) uintptr
|
||||||
|
TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-8
|
||||||
|
MOVL p+0(FP),AX // addr of first arg
|
||||||
|
MOVL AX, ret+4(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
// int64 runtime·cputicks(void), so really
|
// int64 runtime·cputicks(void), so really
|
||||||
// void runtime·cputicks(int64 *ticks)
|
// void runtime·cputicks(int64 *ticks)
|
||||||
TEXT runtime·cputicks(SB),NOSPLIT,$0-4
|
TEXT runtime·cputicks(SB),NOSPLIT,$0-4
|
||||||
|
|
|
||||||
|
|
@ -946,6 +946,12 @@ TEXT runtime·getcallersp(SB),NOSPLIT,$0-8
|
||||||
MOVQ sp+0(FP), AX
|
MOVQ sp+0(FP), AX
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// func gogetcallersp(p unsafe.Pointer) uintptr
|
||||||
|
TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
|
||||||
|
MOVQ p+0(FP),AX // addr of first arg
|
||||||
|
MOVQ AX, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
// int64 runtime·cputicks(void)
|
// int64 runtime·cputicks(void)
|
||||||
TEXT runtime·cputicks(SB),NOSPLIT,$0-0
|
TEXT runtime·cputicks(SB),NOSPLIT,$0-0
|
||||||
RDTSC
|
RDTSC
|
||||||
|
|
|
||||||
|
|
@ -747,6 +747,12 @@ TEXT runtime·getcallersp(SB),NOSPLIT,$0-8
|
||||||
MOVL sp+0(FP), AX
|
MOVL sp+0(FP), AX
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// func gogetcallersp(p unsafe.Pointer) uintptr
|
||||||
|
TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-12
|
||||||
|
MOVL p+0(FP),AX // addr of first arg
|
||||||
|
MOVL AX, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
// int64 runtime·cputicks(void)
|
// int64 runtime·cputicks(void)
|
||||||
TEXT runtime·cputicks(SB),NOSPLIT,$0-0
|
TEXT runtime·cputicks(SB),NOSPLIT,$0-0
|
||||||
RDTSC
|
RDTSC
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,13 @@ TEXT runtime·getcallersp(SB),NOSPLIT,$-4-4
|
||||||
MOVW $-4(R0), R0
|
MOVW $-4(R0), R0
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// func gogetcallersp(p unsafe.Pointer) uintptr
|
||||||
|
TEXT runtime·gogetcallersp(SB),NOSPLIT,$-4-8
|
||||||
|
MOVW 0(FP), R0
|
||||||
|
MOVW $-4(R0), R0
|
||||||
|
MOVW R0, ret+4(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT runtime·emptyfunc(SB),0,$0-0
|
TEXT runtime·emptyfunc(SB),0,$0-0
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,9 +133,3 @@ type BlockProfileRecord struct {
|
||||||
Cycles int64
|
Cycles int64
|
||||||
StackRecord
|
StackRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stack formats a stack trace of the calling goroutine into buf
|
|
||||||
// and returns the number of bytes written to buf.
|
|
||||||
// If all is true, Stack formats stack traces of all other goroutines
|
|
||||||
// into buf after the trace for the current goroutine.
|
|
||||||
func Stack(buf []byte, all bool) int
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,47 @@ func BlockProfile(p []BlockProfileRecord) (n int, ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stack formats a stack trace of the calling goroutine into buf
|
||||||
|
// and returns the number of bytes written to buf.
|
||||||
|
// If all is true, Stack formats stack traces of all other goroutines
|
||||||
|
// into buf after the trace for the current goroutine.
|
||||||
|
func Stack(buf []byte, all bool) int {
|
||||||
|
sp := gogetcallersp(unsafe.Pointer(&buf))
|
||||||
|
pc := gogetcallerpc(unsafe.Pointer(&buf))
|
||||||
|
mp := acquirem()
|
||||||
|
gp := mp.curg
|
||||||
|
if all {
|
||||||
|
semacquire(&worldsema, false)
|
||||||
|
mp.gcing = 1
|
||||||
|
releasem(mp)
|
||||||
|
stoptheworld()
|
||||||
|
if mp != acquirem() {
|
||||||
|
gothrow("Stack: rescheduled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n := 0
|
||||||
|
if len(buf) > 0 {
|
||||||
|
gp.writebuf = &buf[0]
|
||||||
|
gp.writenbuf = int32(len(buf))
|
||||||
|
traceback(pc, sp, 0, gp)
|
||||||
|
if all {
|
||||||
|
tracebackothers(gp)
|
||||||
|
}
|
||||||
|
n = len(buf) - int(gp.writenbuf)
|
||||||
|
gp.writebuf = nil
|
||||||
|
gp.writenbuf = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if all {
|
||||||
|
mp.gcing = 0
|
||||||
|
semrelease(&worldsema)
|
||||||
|
starttheworld()
|
||||||
|
}
|
||||||
|
releasem(mp)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
// ThreadCreateProfile returns n, the number of records in the thread creation profile.
|
// ThreadCreateProfile returns n, the number of records in the thread creation profile.
|
||||||
// If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n, true.
|
// If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n, true.
|
||||||
// If len(p) < n, ThreadCreateProfile does not change p and returns n, false.
|
// If len(p) < n, ThreadCreateProfile does not change p and returns n, false.
|
||||||
|
|
|
||||||
|
|
@ -256,39 +256,6 @@ struct TRecord {
|
||||||
uintptr stk[32];
|
uintptr stk[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
func Stack(b Slice, all bool) (n int) {
|
|
||||||
uintptr pc, sp;
|
|
||||||
|
|
||||||
sp = runtime·getcallersp(&b);
|
|
||||||
pc = (uintptr)runtime·getcallerpc(&b);
|
|
||||||
|
|
||||||
if(all) {
|
|
||||||
runtime·semacquire(&runtime·worldsema, false);
|
|
||||||
g->m->gcing = 1;
|
|
||||||
runtime·stoptheworld();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(b.len == 0)
|
|
||||||
n = 0;
|
|
||||||
else{
|
|
||||||
g->writebuf = (byte*)b.array;
|
|
||||||
g->writenbuf = b.len;
|
|
||||||
runtime·goroutineheader(g);
|
|
||||||
runtime·traceback(pc, sp, 0, g);
|
|
||||||
if(all)
|
|
||||||
runtime·tracebackothers(g);
|
|
||||||
n = b.len - g->writenbuf;
|
|
||||||
g->writebuf = nil;
|
|
||||||
g->writenbuf = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(all) {
|
|
||||||
g->m->gcing = 0;
|
|
||||||
runtime·semrelease(&runtime·worldsema);
|
|
||||||
runtime·starttheworld();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
saveg(uintptr pc, uintptr sp, G *gp, TRecord *r)
|
saveg(uintptr pc, uintptr sp, G *gp, TRecord *r)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ const (
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func gogetcallerpc(p unsafe.Pointer) uintptr
|
func gogetcallerpc(p unsafe.Pointer) uintptr
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func gogetcallersp(p unsafe.Pointer) uintptr
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func racereadpc(addr unsafe.Pointer, callpc, pc uintptr)
|
func racereadpc(addr unsafe.Pointer, callpc, pc uintptr)
|
||||||
|
|
||||||
|
|
@ -212,3 +215,6 @@ func gonotetsleepg(n *note, t int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func exitsyscall()
|
func exitsyscall()
|
||||||
|
|
||||||
|
func traceback(pc, sp, lr uintptr, gp *g)
|
||||||
|
func tracebackothers(gp *g)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue