MOVL SI, (g_sched+gobuf_g)(SI)
LEAL 4(SP), AX // f's SP
MOVL AX, (g_sched+gobuf_sp)(SI)
- MOVL DX, (g_sched+gobuf_ctxt)(SI)
+ // newstack will fill gobuf.ctxt.
// Call newstack on m->g0's stack.
MOVL m_g0(BX), BP
MOVL (g_sched+gobuf_sp)(BP), AX
MOVL -4(AX), BX // fault if CALL would, before smashing SP
MOVL AX, SP
+ PUSHL DX // ctxt argument
CALL runtime·newstack(SB)
MOVL $0, 0x1003 // crash if newstack returns
+ POPL DX // keep balance check happy
RET
TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
MOVQ SI, (g_sched+gobuf_g)(SI)
LEAQ 8(SP), AX // f's SP
MOVQ AX, (g_sched+gobuf_sp)(SI)
- MOVQ DX, (g_sched+gobuf_ctxt)(SI)
MOVQ BP, (g_sched+gobuf_bp)(SI)
+ // newstack will fill gobuf.ctxt.
// Call newstack on m->g0's stack.
MOVQ m_g0(BX), BX
MOVQ BX, g(CX)
MOVQ (g_sched+gobuf_sp)(BX), SP
+ PUSHQ DX // ctxt argument
CALL runtime·newstack(SB)
MOVQ $0, 0x1003 // crash if newstack returns
+ POPQ DX // keep balance check happy
RET
// morestack but not preserving ctxt.
MOVL SI, (g_sched+gobuf_g)(SI)
LEAL 8(SP), AX // f's SP
MOVL AX, (g_sched+gobuf_sp)(SI)
- MOVL DX, (g_sched+gobuf_ctxt)(SI)
+ // newstack will fill gobuf.ctxt.
// Call newstack on m->g0's stack.
MOVL m_g0(BX), BX
MOVL BX, g(CX)
MOVL (g_sched+gobuf_sp)(BX), SP
+ PUSHQ DX // ctxt argument
CALL runtime·newstack(SB)
MOVL $0, 0x1003 // crash if newstack returns
+ POPQ DX // keep balance check happy
RET
// morestack trampolines
// Called from f.
// Set g->sched to context in f.
- MOVW R7, (g_sched+gobuf_ctxt)(g)
MOVW R13, (g_sched+gobuf_sp)(g)
MOVW LR, (g_sched+gobuf_pc)(g)
MOVW R3, (g_sched+gobuf_lr)(g)
+ // newstack will fill gobuf.ctxt.
// Called from f.
// Set m->morebuf to f's caller.
MOVW m_g0(R8), R0
BL setg<>(SB)
MOVW (g_sched+gobuf_sp)(g), R13
+ MOVW $0, R0
+ MOVW.W R0, -8(R13) // create a call frame on g0
+ MOVW R7, 4(R13) // ctxt argument
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// Called from f.
// Set g->sched to context in f
- MOVD R26, (g_sched+gobuf_ctxt)(g)
MOVD RSP, R0
MOVD R0, (g_sched+gobuf_sp)(g)
MOVD LR, (g_sched+gobuf_pc)(g)
MOVD R3, (g_sched+gobuf_lr)(g)
+ // newstack will fill gobuf.ctxt.
// Called from f.
// Set m->morebuf to f's callers.
BL runtime·save_g(SB)
MOVD (g_sched+gobuf_sp)(g), R0
MOVD R0, RSP
+ MOVD.W $0, -16(RSP) // create a call frame on g0
+ MOVD R26, 8(RSP) // ctxt argument
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// Called from f.
// Set g->sched to context in f.
- MOVV REGCTXT, (g_sched+gobuf_ctxt)(g)
MOVV R29, (g_sched+gobuf_sp)(g)
MOVV R31, (g_sched+gobuf_pc)(g)
MOVV R3, (g_sched+gobuf_lr)(g)
+ // newstack will fill gobuf.ctxt.
// Called from f.
// Set m->morebuf to f's caller.
MOVV m_g0(R7), g
JAL runtime·save_g(SB)
MOVV (g_sched+gobuf_sp)(g), R29
+ // Create a stack frame on g0 to call newstack.
+ MOVV R0, -16(R29) // Zero saved LR in frame
+ ADDV $-16, R29
+ MOVV REGCTXT, 8(R29) // ctxt argument
JAL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// Called from f.
// Set g->sched to context in f.
- MOVD R11, (g_sched+gobuf_ctxt)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD LR, R8
MOVD R8, (g_sched+gobuf_pc)(g)
MOVD R5, (g_sched+gobuf_lr)(g)
+ // newstack will fill gobuf.ctxt.
// Called from f.
// Set m->morebuf to f's caller.
MOVD m_g0(R7), g
BL runtime·save_g(SB)
MOVD (g_sched+gobuf_sp)(g), R1
+ MOVDU R0, -(FIXED_FRAME+8)(R1) // create a call frame on g0
+ MOVD R11, FIXED_FRAME+0(R1) // ctxt argument
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// Called from f.
// Set g->sched to context in f.
- MOVD R12, (g_sched+gobuf_ctxt)(g)
MOVD R15, (g_sched+gobuf_sp)(g)
MOVD LR, R8
MOVD R8, (g_sched+gobuf_pc)(g)
MOVD R5, (g_sched+gobuf_lr)(g)
+ // newstack will fill gobuf.ctxt.
// Called from f.
// Set m->morebuf to f's caller.
MOVD m_g0(R7), g
BL runtime·save_g(SB)
MOVD (g_sched+gobuf_sp)(g), R15
+ // Create a stack frame on g0 to call newstack.
+ MOVD $0, -16(R15) // Zero saved LR in frame
+ SUB $16, R15
+ MOVD R12, 8(R15) // ctxt argument
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
//
// g->atomicstatus will be Grunning or Gscanrunning upon entry.
// If the GC is trying to stop this g then it will set preemptscan to true.
-func newstack() {
+//
+// ctxt is the value of the context register on morestack. newstack
+// will write it to g.sched.ctxt.
+func newstack(ctxt unsafe.Pointer) {
thisg := getg()
// TODO: double check all gp. shouldn't be getg().
if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
throw("runtime: wrong goroutine in newstack")
}
+
+ gp := thisg.m.curg
+ // Write ctxt to gp.sched. We do this here instead of in
+ // morestack so it has the necessary write barrier.
+ gp.sched.ctxt = ctxt
+
if thisg.m.curg.throwsplit {
- gp := thisg.m.curg
// Update syscallsp, syscallpc in case traceback uses them.
morebuf := thisg.m.morebuf
gp.syscallsp = morebuf.sp
throw("runtime: stack split at bad time")
}
- gp := thisg.m.curg
morebuf := thisg.m.morebuf
thisg.m.morebuf.pc = 0
thisg.m.morebuf.lr = 0
throw("runtime: split stack overflow")
}
- if gp.sched.ctxt != nil {
- // morestack wrote sched.ctxt on its way in here,
- // without a write barrier. Run the write barrier now.
- // It is not possible to be preempted between then
- // and now, so it's okay.
- writebarrierptr_nostore((*uintptr)(unsafe.Pointer(&gp.sched.ctxt)), uintptr(gp.sched.ctxt))
- }
-
if preempt {
if gp == thisg.m.g0 {
throw("runtime: preempt g0")