aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgcwork.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-08-16 12:25:38 -0400
committerAustin Clements <austin@google.com>2018-10-02 20:35:34 +0000
commit457c8f4fe9e4d45f97d0a3f3c4a80789c6616fd6 (patch)
treeb5869505da8c2e5b9b6c9ec745a07495e3797de1 /src/runtime/mgcwork.go
parent143b13ae82d81020dfa6db40818bef5a1f701c3f (diff)
downloadgo-457c8f4fe9e4d45f97d0a3f3c4a80789c6616fd6.tar.xz
runtime: eliminate blocking GC work drains
Now work.helperDrainBlock is always false, so we can remove it and code paths that only ran when it was true. That means we no longer use the gcDrainBlock mode of gcDrain, so we can eliminate that. That means we no longer use gcWork.get, so we can eliminate that. That means we no longer use getfull, so we can eliminate that. Updates #26903. This is a follow-up to unifying STW GC and concurrent GC. Change-Id: I8dbcf8ce24861df0a6149e0b7c5cd0eadb5c13f6 Reviewed-on: https://go-review.googlesource.com/c/134782 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rick Hudson <rlh@golang.org>
Diffstat (limited to 'src/runtime/mgcwork.go')
-rw-r--r--src/runtime/mgcwork.go88
1 files changed, 1 insertions, 87 deletions
diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go
index 3a99260e53..c32c5eddd7 100644
--- a/src/runtime/mgcwork.go
+++ b/src/runtime/mgcwork.go
@@ -46,7 +46,7 @@ func init() {
//
// (preemption must be disabled)
// gcw := &getg().m.p.ptr().gcw
-// .. call gcw.put() to produce and gcw.get() to consume ..
+// .. call gcw.put() to produce and gcw.tryGet() to consume ..
//
// It's important that any use of gcWork during the mark phase prevent
// the garbage collector from transitioning to mark termination since
@@ -236,37 +236,6 @@ func (w *gcWork) tryGetFast() uintptr {
return wbuf.obj[wbuf.nobj]
}
-// get dequeues a pointer for the garbage collector to trace, blocking
-// if necessary to ensure all pointers from all queues and caches have
-// been retrieved. get returns 0 if there are no pointers remaining.
-//go:nowritebarrierrec
-func (w *gcWork) get() uintptr {
- wbuf := w.wbuf1
- if wbuf == nil {
- w.init()
- wbuf = w.wbuf1
- // wbuf is empty at this point.
- }
- if wbuf.nobj == 0 {
- w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
- wbuf = w.wbuf1
- if wbuf.nobj == 0 {
- owbuf := wbuf
- wbuf = getfull()
- if wbuf == nil {
- return 0
- }
- putempty(owbuf)
- w.wbuf1 = wbuf
- }
- }
-
- // TODO: This might be a good place to add prefetch code
-
- wbuf.nobj--
- return wbuf.obj[wbuf.nobj]
-}
-
// dispose returns any cached pointers to the global queue.
// The buffers are being put on the full queue so that the
// write barriers will not simply reacquire them before the
@@ -449,61 +418,6 @@ func trygetfull() *workbuf {
return b
}
-// Get a full work buffer off the work.full list.
-// If nothing is available wait until all the other gc helpers have
-// finished and then return nil.
-// getfull acts as a barrier for work.nproc helpers. As long as one
-// gchelper is actively marking objects it
-// may create a workbuffer that the other helpers can work on.
-// The for loop either exits when a work buffer is found
-// or when _all_ of the work.nproc GC helpers are in the loop
-// looking for work and thus not capable of creating new work.
-// This is in fact the termination condition for the STW mark
-// phase.
-//go:nowritebarrier
-func getfull() *workbuf {
- b := (*workbuf)(work.full.pop())
- if b != nil {
- b.checknonempty()
- return b
- }
-
- incnwait := atomic.Xadd(&work.nwait, +1)
- if incnwait > work.nproc {
- println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- for i := 0; ; i++ {
- if work.full != 0 {
- decnwait := atomic.Xadd(&work.nwait, -1)
- if decnwait == work.nproc {
- println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- b = (*workbuf)(work.full.pop())
- if b != nil {
- b.checknonempty()
- return b
- }
- incnwait := atomic.Xadd(&work.nwait, +1)
- if incnwait > work.nproc {
- println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- }
- if work.nwait == work.nproc && work.markrootNext >= work.markrootJobs {
- return nil
- }
- if i < 10 {
- procyield(20)
- } else if i < 20 {
- osyield()
- } else {
- usleep(100)
- }
- }
-}
-
//go:nowritebarrier
func handoff(b *workbuf) *workbuf {
// Make new buffer with half of b's pointers.