// gcRemoveStackBarrier removes a single stack barrier. It is the // inverse operation of gcInstallStackBarrier. // // This is nosplit to ensure gp's stack does not move. // //go:nowritebarrier //go:nosplit func gcRemoveStackBarrier(gp *g, stkbar stkbar) { if debugStackBarrier { print("remove stack barrier at ", hex(stkbar.savedLRPtr), " with ", hex(stkbar.savedLRVal), ", goid=", gp.goid, "\n") } lrPtr := (*sys.Uintreg)(unsafe.Pointer(stkbar.savedLRPtr)) if val := *lrPtr; val != sys.Uintreg(stackBarrierPC) { printlock() print("at *", hex(stkbar.savedLRPtr), " expected stack barrier PC ", hex(stackBarrierPC), ", found ", hex(val), ", goid=", gp.goid, "\n") print("gp.stkbar=") gcPrintStkbars(gp, -1) print(", gp.stack=[", hex(gp.stack.lo), ",", hex(gp.stack.hi), ")\n") throw("stack barrier lost") } *lrPtr = sys.Uintreg(stkbar.savedLRVal) }
// gcInstallStackBarrier installs a stack barrier over the return PC of frame. //go:nowritebarrier func gcInstallStackBarrier(gp *g, frame *stkframe) bool { if frame.lr == 0 { if debugStackBarrier { print("not installing stack barrier with no LR, goid=", gp.goid, "\n") } return false } if frame.fn.entry == cgocallback_gofuncPC { // cgocallback_gofunc doesn't return to its LR; // instead, its return path puts LR in g.sched.pc and // switches back to the system stack on which // cgocallback_gofunc was originally called. We can't // have a stack barrier in g.sched.pc, so don't // install one in this frame. if debugStackBarrier { print("not installing stack barrier over LR of cgocallback_gofunc, goid=", gp.goid, "\n") } return false } // Save the return PC and overwrite it with stackBarrier. var lrUintptr uintptr if usesLR { lrUintptr = frame.sp } else { lrUintptr = frame.fp - sys.RegSize } lrPtr := (*sys.Uintreg)(unsafe.Pointer(lrUintptr)) if debugStackBarrier { print("install stack barrier at ", hex(lrUintptr), " over ", hex(*lrPtr), ", goid=", gp.goid, "\n") if uintptr(*lrPtr) != frame.lr { print("frame.lr=", hex(frame.lr)) throw("frame.lr differs from stack LR") } } gp.stkbar = gp.stkbar[:len(gp.stkbar)+1] stkbar := &gp.stkbar[len(gp.stkbar)-1] stkbar.savedLRPtr = lrUintptr stkbar.savedLRVal = uintptr(*lrPtr) *lrPtr = sys.Uintreg(stackBarrierPC) return true }