aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgcwork.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/mgcwork.go')
-rw-r--r--src/runtime/mgcwork.go34
1 files changed, 19 insertions, 15 deletions
diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go
index da2129ee50..8a77ff55e4 100644
--- a/src/runtime/mgcwork.go
+++ b/src/runtime/mgcwork.go
@@ -93,6 +93,10 @@ type gcWork struct {
// termination check. Specifically, this indicates that this
// gcWork may have communicated work to another gcWork.
flushedWork bool
+
+ // pauseGen causes put operations to spin while pauseGen ==
+ // gcWorkPauseGen if debugCachedWork is true.
+ pauseGen uint32
}
// Most of the methods of gcWork are go:nowritebarrierrec because the
@@ -111,13 +115,21 @@ func (w *gcWork) init() {
w.wbuf2 = wbuf2
}
+func (w *gcWork) checkPut() {
+ if debugCachedWork {
+ for atomic.Load(&gcWorkPauseGen) == w.pauseGen {
+ }
+ if throwOnGCWork {
+ throw("throwOnGCWork")
+ }
+ }
+}
+
// put enqueues a pointer for the garbage collector to trace.
// obj must point to the beginning of a heap object or an oblet.
//go:nowritebarrierrec
func (w *gcWork) put(obj uintptr) {
- if throwOnGCWork {
- throw("throwOnGCWork")
- }
+ w.checkPut()
flushed := false
wbuf := w.wbuf1
@@ -153,9 +165,7 @@ func (w *gcWork) put(obj uintptr) {
// otherwise it returns false and the caller needs to call put.
//go:nowritebarrierrec
func (w *gcWork) putFast(obj uintptr) bool {
- if throwOnGCWork {
- throw("throwOnGCWork")
- }
+ w.checkPut()
wbuf := w.wbuf1
if wbuf == nil {
@@ -178,9 +188,7 @@ func (w *gcWork) putBatch(obj []uintptr) {
return
}
- if throwOnGCWork {
- throw("throwOnGCWork")
- }
+ w.checkPut()
flushed := false
wbuf := w.wbuf1
@@ -303,16 +311,12 @@ func (w *gcWork) balance() {
return
}
if wbuf := w.wbuf2; wbuf.nobj != 0 {
- if throwOnGCWork {
- throw("throwOnGCWork")
- }
+ w.checkPut()
putfull(wbuf)
w.flushedWork = true
w.wbuf2 = getempty()
} else if wbuf := w.wbuf1; wbuf.nobj > 4 {
- if throwOnGCWork {
- throw("throwOnGCWork")
- }
+ w.checkPut()
w.wbuf1 = handoff(wbuf)
w.flushedWork = true // handoff did putfull
} else {