diff options
Diffstat (limited to 'libgo/go/runtime/mstkbar.go')
-rw-r--r-- | libgo/go/runtime/mstkbar.go | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/libgo/go/runtime/mstkbar.go b/libgo/go/runtime/mstkbar.go index 016625ae925..1bf9d573b70 100644 --- a/libgo/go/runtime/mstkbar.go +++ b/libgo/go/runtime/mstkbar.go @@ -214,14 +214,15 @@ func gcInstallStackBarrier(gp *g, frame *stkframe) bool { } // gcRemoveStackBarriers removes all stack barriers installed in gp's stack. +// +// gp's stack barriers must be locked. +// //go:nowritebarrier func gcRemoveStackBarriers(gp *g) { if debugStackBarrier && gp.stkbarPos != 0 { print("hit ", gp.stkbarPos, " stack barriers, goid=", gp.goid, "\n") } - gcLockStackBarriers(gp) - // Remove stack barriers that we didn't hit. for _, stkbar := range gp.stkbar[gp.stkbarPos:] { gcRemoveStackBarrier(gp, stkbar) @@ -231,8 +232,6 @@ func gcRemoveStackBarriers(gp *g) { // adjust them. gp.stkbarPos = 0 gp.stkbar = gp.stkbar[:0] - - gcUnlockStackBarriers(gp) } // gcRemoveStackBarrier removes a single stack barrier. It is the @@ -258,6 +257,31 @@ func gcRemoveStackBarrier(gp *g, stkbar stkbar) { *lrPtr = sys.Uintreg(stkbar.savedLRVal) } +// gcTryRemoveAllStackBarriers tries to remove stack barriers from all +// Gs in gps. It is best-effort and efficient. If it can't remove +// barriers from a G immediately, it will simply skip it. +func gcTryRemoveAllStackBarriers(gps []*g) { + for _, gp := range gps { + retry: + for { + switch s := readgstatus(gp); s { + default: + break retry + + case _Grunnable, _Gsyscall, _Gwaiting: + if !castogscanstatus(gp, s, s|_Gscan) { + continue + } + gcLockStackBarriers(gp) + gcRemoveStackBarriers(gp) + gcUnlockStackBarriers(gp) + restartg(gp) + break retry + } + } + } +} + // gcPrintStkbars prints the stack barriers of gp for debugging. It // places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also // place a "==>" marker before the marker'th entry. |