]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: change top-most return PC from goexit to goexit+PCQuantum
authorRuss Cox <rsc@golang.org>
Thu, 30 Oct 2014 00:37:44 +0000 (20:37 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 30 Oct 2014 00:37:44 +0000 (20:37 -0400)
If you get a stack of PCs from Callers, it would be expected
that every PC is immediately after a call instruction, so to find
the line of the call, you look up the line for PC-1.
CL 163550043 now explicitly documents that.

The most common exception to this is the top-most return PC
on the stack, which is the entry address of the runtime.goexit
function. Subtracting 1 from that PC will end up in a different
function entirely.

To remove this special case, make the top-most return PC
goexit+PCQuantum and then implement goexit in assembly
so that the first instruction can be skipped.

Fixes #7690.

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/170720043

src/runtime/asm_386.s
src/runtime/asm_amd64.s
src/runtime/asm_amd64p32.s
src/runtime/asm_arm.s
src/runtime/proc.c

index 0d46a9eff78035a6fca583a0f4b6800c32cabcde..b4b81d7397eb03f169aa527eab2d639cb6deb20a 100644 (file)
@@ -2284,3 +2284,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
        MOVL    m_curg(AX), AX
        MOVL    (g_stack+stack_hi)(AX), AX
        RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
+       BYTE    $0x90   // NOP
+       CALL    runtime·goexit1(SB)    // does not return
index a9b082beb82a66f28d9e808166f66e334415de3e..39d7c78f23346f9ed87259f324811d4c8b6538ba 100644 (file)
@@ -2229,3 +2229,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
        MOVQ    m_curg(AX), AX
        MOVQ    (g_stack+stack_hi)(AX), AX
        RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
+       BYTE    $0x90   // NOP
+       CALL    runtime·goexit1(SB)    // does not return
index 28875bc55a146a4e386b68c58f4731f3de0288ea..a1116b5d471ed35a44bd7a7a5c6d5c6d6816fc18 100644 (file)
@@ -1079,3 +1079,9 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
 TEXT runtime·return0(SB), NOSPLIT, $0
        MOVL    $0, AX
        RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$0-0
+       BYTE    $0x90   // NOP
+       CALL    runtime·goexit1(SB)    // does not return
index e94b4c1ff61560f3424b45ff0dc9c758980e1dae..0f3b5eeb8bd338d7087c4d969367443ea57a3670 100644 (file)
@@ -1320,3 +1320,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8
        MOVW    saveG-8(SP), g
        MOVW    saveR11-4(SP), R11
        RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-4-0
+       MOVW    R0, R0  // NOP
+       BL      runtime·goexit1(SB)    // does not return
index b46f67065a528b92182b5ef29565250eb4fa3a8f..4be51e1e1660919cd74bac530b0061425997e7c6 100644 (file)
@@ -1643,12 +1643,10 @@ runtime·gosched_m(G *gp)
 }
 
 // Finishes execution of the current goroutine.
-// Need to mark it as nosplit, because it runs with sp > stackbase.
-// Since it does not return it does not matter.  But if it is preempted
-// at the split stack check, GC will complain about inconsistent sp.
+// Must be NOSPLIT because it is called from Go.
 #pragma textflag NOSPLIT
 void
-runtime·goexit(void)
+runtime·goexit1(void)
 {
        void (*fn)(G*);
 
@@ -2192,7 +2190,7 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
 
        runtime·memclr((byte*)&newg->sched, sizeof newg->sched);
        newg->sched.sp = (uintptr)sp;
-       newg->sched.pc = (uintptr)runtime·goexit;
+       newg->sched.pc = (uintptr)runtime·goexit + PCQuantum; // +PCQuantum so that previous instruction is in same function
        newg->sched.g = newg;
        runtime·gostartcallfn(&newg->sched, fn);
        newg->gopc = (uintptr)callerpc;