summaryrefslogtreecommitdiff
path: root/libgo/go/runtime/mstkbar.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/mstkbar.go')
-rw-r--r--libgo/go/runtime/mstkbar.go32
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.