Skip to content

Commit bf9c71c

Browse files
committed
runtime: make morestack less subtle
morestack writes the context pointer to gobuf.ctxt, but since morestack is written in assembly (and has to be very careful with state), it does *not* invoke the requisite write barrier for this write. Instead, we patch this up later, in newstack, where we invoke an explicit write barrier for ctxt. This already requires some subtle reasoning, and it's going to get a lot hairier with the hybrid barrier. Fix this by simplifying the whole mechanism. Instead of writing gobuf.ctxt in morestack, just pass the value of the context register to newstack and let it write it to gobuf.ctxt. This is a normal Go pointer write, so it gets the normal Go write barrier. No subtle reasoning required. Updates #17503. Change-Id: Ia6bf8459bfefc6828f53682ade32c02412e4db63 Reviewed-on: https://go-review.googlesource.com/31550 Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent cdccd6a commit bf9c71c

File tree

9 files changed

+39
-19
lines changed

9 files changed

+39
-19
lines changed

src/runtime/asm_386.s

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,18 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
381381
MOVL SI, (g_sched+gobuf_g)(SI)
382382
LEAL 4(SP), AX // f's SP
383383
MOVL AX, (g_sched+gobuf_sp)(SI)
384-
MOVL DX, (g_sched+gobuf_ctxt)(SI)
384+
// newstack will fill gobuf.ctxt.
385385

386386
// Call newstack on m->g0's stack.
387387
MOVL m_g0(BX), BP
388388
MOVL BP, g(CX)
389389
MOVL (g_sched+gobuf_sp)(BP), AX
390390
MOVL -4(AX), BX // fault if CALL would, before smashing SP
391391
MOVL AX, SP
392+
PUSHL DX // ctxt argument
392393
CALL runtime·newstack(SB)
393394
MOVL $0, 0x1003 // crash if newstack returns
395+
POPL DX // keep balance check happy
394396
RET
395397

396398
TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0

src/runtime/asm_amd64.s

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,17 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
358358
MOVQ SI, (g_sched+gobuf_g)(SI)
359359
LEAQ 8(SP), AX // f's SP
360360
MOVQ AX, (g_sched+gobuf_sp)(SI)
361-
MOVQ DX, (g_sched+gobuf_ctxt)(SI)
362361
MOVQ BP, (g_sched+gobuf_bp)(SI)
362+
// newstack will fill gobuf.ctxt.
363363

364364
// Call newstack on m->g0's stack.
365365
MOVQ m_g0(BX), BX
366366
MOVQ BX, g(CX)
367367
MOVQ (g_sched+gobuf_sp)(BX), SP
368+
PUSHQ DX // ctxt argument
368369
CALL runtime·newstack(SB)
369370
MOVQ $0, 0x1003 // crash if newstack returns
371+
POPQ DX // keep balance check happy
370372
RET
371373

372374
// morestack but not preserving ctxt.

src/runtime/asm_amd64p32.s

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,16 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
276276
MOVL SI, (g_sched+gobuf_g)(SI)
277277
LEAL 8(SP), AX // f's SP
278278
MOVL AX, (g_sched+gobuf_sp)(SI)
279-
MOVL DX, (g_sched+gobuf_ctxt)(SI)
279+
// newstack will fill gobuf.ctxt.
280280

281281
// Call newstack on m->g0's stack.
282282
MOVL m_g0(BX), BX
283283
MOVL BX, g(CX)
284284
MOVL (g_sched+gobuf_sp)(BX), SP
285+
PUSHQ DX // ctxt argument
285286
CALL runtime·newstack(SB)
286287
MOVL $0, 0x1003 // crash if newstack returns
288+
POPQ DX // keep balance check happy
287289
RET
288290

289291
// morestack trampolines

src/runtime/asm_arm.s

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,10 @@ TEXT runtime·morestack(SB),NOSPLIT,$-4-0
294294

295295
// Called from f.
296296
// Set g->sched to context in f.
297-
MOVW R7, (g_sched+gobuf_ctxt)(g)
298297
MOVW R13, (g_sched+gobuf_sp)(g)
299298
MOVW LR, (g_sched+gobuf_pc)(g)
300299
MOVW R3, (g_sched+gobuf_lr)(g)
300+
// newstack will fill gobuf.ctxt.
301301

302302
// Called from f.
303303
// Set m->morebuf to f's caller.
@@ -310,6 +310,9 @@ TEXT runtime·morestack(SB),NOSPLIT,$-4-0
310310
MOVW m_g0(R8), R0
311311
BL setg<>(SB)
312312
MOVW (g_sched+gobuf_sp)(g), R13
313+
MOVW $0, R0
314+
MOVW.W R0, -8(R13) // create a call frame on g0
315+
MOVW R7, 4(R13) // ctxt argument
313316
BL runtime·newstack(SB)
314317

315318
// Not reached, but make sure the return PC from the call to newstack

src/runtime/asm_arm64.s

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,11 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
269269

270270
// Called from f.
271271
// Set g->sched to context in f
272-
MOVD R26, (g_sched+gobuf_ctxt)(g)
273272
MOVD RSP, R0
274273
MOVD R0, (g_sched+gobuf_sp)(g)
275274
MOVD LR, (g_sched+gobuf_pc)(g)
276275
MOVD R3, (g_sched+gobuf_lr)(g)
276+
// newstack will fill gobuf.ctxt.
277277

278278
// Called from f.
279279
// Set m->morebuf to f's callers.
@@ -287,6 +287,8 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
287287
BL runtime·save_g(SB)
288288
MOVD (g_sched+gobuf_sp)(g), R0
289289
MOVD R0, RSP
290+
MOVD.W $0, -16(RSP) // create a call frame on g0
291+
MOVD R26, 8(RSP) // ctxt argument
290292
BL runtime·newstack(SB)
291293

292294
// Not reached, but make sure the return PC from the call to newstack

src/runtime/asm_mips64x.s

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,10 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
243243

244244
// Called from f.
245245
// Set g->sched to context in f.
246-
MOVV REGCTXT, (g_sched+gobuf_ctxt)(g)
247246
MOVV R29, (g_sched+gobuf_sp)(g)
248247
MOVV R31, (g_sched+gobuf_pc)(g)
249248
MOVV R3, (g_sched+gobuf_lr)(g)
249+
// newstack will fill gobuf.ctxt.
250250

251251
// Called from f.
252252
// Set m->morebuf to f's caller.
@@ -258,6 +258,10 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
258258
MOVV m_g0(R7), g
259259
JAL runtime·save_g(SB)
260260
MOVV (g_sched+gobuf_sp)(g), R29
261+
// Create a stack frame on g0 to call newstack.
262+
MOVV R0, -16(R29) // Zero saved LR in frame
263+
ADDV $-16, R29
264+
MOVV REGCTXT, 8(R29) // ctxt argument
261265
JAL runtime·newstack(SB)
262266

263267
// Not reached, but make sure the return PC from the call to newstack

src/runtime/asm_ppc64x.s

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
297297

298298
// Called from f.
299299
// Set g->sched to context in f.
300-
MOVD R11, (g_sched+gobuf_ctxt)(g)
301300
MOVD R1, (g_sched+gobuf_sp)(g)
302301
MOVD LR, R8
303302
MOVD R8, (g_sched+gobuf_pc)(g)
304303
MOVD R5, (g_sched+gobuf_lr)(g)
304+
// newstack will fill gobuf.ctxt.
305305

306306
// Called from f.
307307
// Set m->morebuf to f's caller.
@@ -313,6 +313,8 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
313313
MOVD m_g0(R7), g
314314
BL runtime·save_g(SB)
315315
MOVD (g_sched+gobuf_sp)(g), R1
316+
MOVDU R0, -(FIXED_FRAME+8)(R1) // create a call frame on g0
317+
MOVD R11, FIXED_FRAME+0(R1) // ctxt argument
316318
BL runtime·newstack(SB)
317319

318320
// Not reached, but make sure the return PC from the call to newstack

src/runtime/asm_s390x.s

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,11 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
254254

255255
// Called from f.
256256
// Set g->sched to context in f.
257-
MOVD R12, (g_sched+gobuf_ctxt)(g)
258257
MOVD R15, (g_sched+gobuf_sp)(g)
259258
MOVD LR, R8
260259
MOVD R8, (g_sched+gobuf_pc)(g)
261260
MOVD R5, (g_sched+gobuf_lr)(g)
261+
// newstack will fill gobuf.ctxt.
262262

263263
// Called from f.
264264
// Set m->morebuf to f's caller.
@@ -270,6 +270,10 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
270270
MOVD m_g0(R7), g
271271
BL runtime·save_g(SB)
272272
MOVD (g_sched+gobuf_sp)(g), R15
273+
// Create a stack frame on g0 to call newstack.
274+
MOVD $0, -16(R15) // Zero saved LR in frame
275+
SUB $16, R15
276+
MOVD R12, 8(R15) // ctxt argument
273277
BL runtime·newstack(SB)
274278

275279
// Not reached, but make sure the return PC from the call to newstack

src/runtime/stack.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,10 @@ func round2(x int32) int32 {
925925
//
926926
// g->atomicstatus will be Grunning or Gscanrunning upon entry.
927927
// If the GC is trying to stop this g then it will set preemptscan to true.
928-
func newstack() {
928+
//
929+
// ctxt is the value of the context register on morestack. newstack
930+
// will write it to g.sched.ctxt.
931+
func newstack(ctxt unsafe.Pointer) {
929932
thisg := getg()
930933
// TODO: double check all gp. shouldn't be getg().
931934
if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
@@ -937,8 +940,13 @@ func newstack() {
937940
traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
938941
throw("runtime: wrong goroutine in newstack")
939942
}
943+
944+
gp := thisg.m.curg
945+
// Write ctxt to gp.sched. We do this here instead of in
946+
// morestack so it has the necessary write barrier.
947+
gp.sched.ctxt = ctxt
948+
940949
if thisg.m.curg.throwsplit {
941-
gp := thisg.m.curg
942950
// Update syscallsp, syscallpc in case traceback uses them.
943951
morebuf := thisg.m.morebuf
944952
gp.syscallsp = morebuf.sp
@@ -951,7 +959,6 @@ func newstack() {
951959
throw("runtime: stack split at bad time")
952960
}
953961

954-
gp := thisg.m.curg
955962
morebuf := thisg.m.morebuf
956963
thisg.m.morebuf.pc = 0
957964
thisg.m.morebuf.lr = 0
@@ -1003,14 +1010,6 @@ func newstack() {
10031010
throw("runtime: split stack overflow")
10041011
}
10051012

1006-
if gp.sched.ctxt != nil {
1007-
// morestack wrote sched.ctxt on its way in here,
1008-
// without a write barrier. Run the write barrier now.
1009-
// It is not possible to be preempted between then
1010-
// and now, so it's okay.
1011-
writebarrierptr_nostore((*uintptr)(unsafe.Pointer(&gp.sched.ctxt)), uintptr(gp.sched.ctxt))
1012-
}
1013-
10141013
if preempt {
10151014
if gp == thisg.m.g0 {
10161015
throw("runtime: preempt g0")

0 commit comments

Comments
 (0)