aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgc.go
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2020-10-14 17:18:27 -0400
committerMichael Pratt <mpratt@google.com>2020-10-15 15:55:19 +0000
commit2517f4946b42b8deedb864c884f1b41311d45850 (patch)
treefcd02112f74fc6f5fd816c989a0a7641cd0b10df /src/runtime/mgc.go
parentaa161e799df7e1eba99d2be10271e76b6f758142 (diff)
downloadgo-2517f4946b42b8deedb864c884f1b41311d45850.tar.gz
go-2517f4946b42b8deedb864c884f1b41311d45850.zip
runtime: remove debugCachedWork
debugCachedWork and all of its dependent fields and code were added to aid in debugging issue #27993. Now that the source of the problem is known and mitigated (via the extra work check after STW in gcMarkDone), these extra checks are no longer required and simply make the code more difficult to follow. Remove it all. Updates #27993 Change-Id: I594beedd5ca61733ba9cc9eaad8f80ea92df1a0d Reviewed-on: https://go-review.googlesource.com/c/go/+/262350 Trust: Michael Pratt <mpratt@google.com> Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/mgc.go')
-rw-r--r--src/runtime/mgc.go121
1 files changed, 24 insertions, 97 deletions
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index bd87144355..0a4d5616a5 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -1407,19 +1407,6 @@ func gcStart(trigger gcTrigger) {
// This is protected by markDoneSema.
var gcMarkDoneFlushed uint32
-// debugCachedWork enables extra checks for debugging premature mark
-// termination.
-//
-// For debugging issue #27993.
-const debugCachedWork = false
-
-// gcWorkPauseGen is for debugging the mark completion algorithm.
-// gcWork put operations spin while gcWork.pauseGen == gcWorkPauseGen.
-// Only used if debugCachedWork is true.
-//
-// For debugging issue #27993.
-var gcWorkPauseGen uint32 = 1
-
// gcMarkDone transitions the GC from mark to mark termination if all
// reachable objects have been marked (that is, there are no grey
// objects and can be no more in the future). Otherwise, it flushes
@@ -1475,15 +1462,7 @@ top:
// Flush the write barrier buffer, since this may add
// work to the gcWork.
wbBufFlush1(_p_)
- // For debugging, shrink the write barrier
- // buffer so it flushes immediately.
- // wbBuf.reset will keep it at this size as
- // long as throwOnGCWork is set.
- if debugCachedWork {
- b := &_p_.wbBuf
- b.end = uintptr(unsafe.Pointer(&b.buf[wbBufEntryPointers]))
- b.debugGen = gcWorkPauseGen
- }
+
// Flush the gcWork, since this may create global work
// and set the flushedWork flag.
//
@@ -1494,29 +1473,12 @@ top:
if _p_.gcw.flushedWork {
atomic.Xadd(&gcMarkDoneFlushed, 1)
_p_.gcw.flushedWork = false
- } else if debugCachedWork {
- // For debugging, freeze the gcWork
- // until we know whether we've reached
- // completion or not. If we think
- // we've reached completion, but
- // there's a paused gcWork, then
- // that's a bug.
- _p_.gcw.pauseGen = gcWorkPauseGen
- // Capture the G's stack.
- for i := range _p_.gcw.pauseStack {
- _p_.gcw.pauseStack[i] = 0
- }
- callers(1, _p_.gcw.pauseStack[:])
}
})
casgstatus(gp, _Gwaiting, _Grunning)
})
if gcMarkDoneFlushed != 0 {
- if debugCachedWork {
- // Release paused gcWorks.
- atomic.Xadd(&gcWorkPauseGen, 1)
- }
// More grey objects were discovered since the
// previous termination check, so there may be more
// work to do. Keep going. It's possible the
@@ -1526,13 +1488,6 @@ top:
goto top
}
- if debugCachedWork {
- throwOnGCWork = true
- // Release paused gcWorks. If there are any, they
- // should now observe throwOnGCWork and panic.
- atomic.Xadd(&gcWorkPauseGen, 1)
- }
-
// There was no global work, no local work, and no Ps
// communicated work since we took markDoneSema. Therefore
// there are no grey objects and no more objects can be
@@ -1549,59 +1504,33 @@ top:
// below. The important thing is that the wb remains active until
// all marking is complete. This includes writes made by the GC.
- if debugCachedWork {
- // For debugging, double check that no work was added after we
- // went around above and disable write barrier buffering.
+ // There is sometimes work left over when we enter mark termination due
+ // to write barriers performed after the completion barrier above.
+ // Detect this and resume concurrent mark. This is obviously
+ // unfortunate.
+ //
+ // See issue #27993 for details.
+ //
+ // Switch to the system stack to call wbBufFlush1, though in this case
+ // it doesn't matter because we're non-preemptible anyway.
+ restart := false
+ systemstack(func() {
for _, p := range allp {
- gcw := &p.gcw
- if !gcw.empty() {
- printlock()
- print("runtime: P ", p.id, " flushedWork ", gcw.flushedWork)
- if gcw.wbuf1 == nil {
- print(" wbuf1=<nil>")
- } else {
- print(" wbuf1.n=", gcw.wbuf1.nobj)
- }
- if gcw.wbuf2 == nil {
- print(" wbuf2=<nil>")
- } else {
- print(" wbuf2.n=", gcw.wbuf2.nobj)
- }
- print("\n")
- if gcw.pauseGen == gcw.putGen {
- println("runtime: checkPut already failed at this generation")
- }
- throw("throwOnGCWork")
+ wbBufFlush1(p)
+ if !p.gcw.empty() {
+ restart = true
+ break
}
}
- } else {
- // For unknown reasons (see issue #27993), there is
- // sometimes work left over when we enter mark
- // termination. Detect this and resume concurrent
- // mark. This is obviously unfortunate.
- //
- // Switch to the system stack to call wbBufFlush1,
- // though in this case it doesn't matter because we're
- // non-preemptible anyway.
- restart := false
+ })
+ if restart {
+ getg().m.preemptoff = ""
systemstack(func() {
- for _, p := range allp {
- wbBufFlush1(p)
- if !p.gcw.empty() {
- restart = true
- break
- }
- }
+ now := startTheWorldWithSema(true)
+ work.pauseNS += now - work.pauseStart
})
- if restart {
- getg().m.preemptoff = ""
- systemstack(func() {
- now := startTheWorldWithSema(true)
- work.pauseNS += now - work.pauseStart
- })
- semrelease(&worldsema)
- goto top
- }
+ semrelease(&worldsema)
+ goto top
}
// Disable assists and background workers. We must do
@@ -2085,7 +2014,7 @@ func gcMark(start_time int64) {
// ensured all reachable objects were marked, all of
// these must be pointers to black objects. Hence we
// can just discard the write barrier buffer.
- if debug.gccheckmark > 0 || throwOnGCWork {
+ if debug.gccheckmark > 0 {
// For debugging, flush the buffer and make
// sure it really was all marked.
wbBufFlush1(p)
@@ -2117,8 +2046,6 @@ func gcMark(start_time int64) {
gcw.dispose()
}
- throwOnGCWork = false
-
cachestats()
// Update the marked heap stat.