bgMarkReady note // signal background mark worker has started
bgMarkDone uint32 // cas to 1 when at a background mark completion point
- bgMarkNote note // signal background mark completion
+
+ // Background mark completion signaling
+ bgMarkWake struct {
+ lock mutex
+ g *g
+ wake bool
+ }
// Copy of mheap.allspans for marker or sweeper.
spans []*mspan
if debug.gctrace > 0 {
tMark = nanotime()
}
- notetsleepg(&work.bgMarkNote, -1)
- noteclear(&work.bgMarkNote)
+
+ // Wait for background mark completion.
+ lock(&work.bgMarkWake.lock)
+ if work.bgMarkWake.wake {
+ // Wakeup already happened
+ unlock(&work.bgMarkWake.lock)
+ } else {
+ work.bgMarkWake.g = getg()
+ goparkunlock(&work.bgMarkWake.lock, "mark wait (idle)", traceEvGoBlock, 1)
+ }
+ work.bgMarkWake.wake = false
+ work.bgMarkWake.g = nil
// Begin mark termination.
gctimer.cycle.markterm = nanotime()
}
gcw.dispose()
- // If this is the first worker to reach a background
- // completion point this cycle, signal the coordinator.
- if done && cas(&work.bgMarkDone, 0, 1) {
- notewakeup(&work.bgMarkNote)
+ // If this worker reached a background mark completion
+ // point, signal the main GC goroutine.
+ if done {
+ gcBgMarkDone()
}
duration := nanotime() - startTime
}
}
+// gcBgMarkDone signals the completion of background marking. This can
+// be called multiple times during a cycle; only the first call has
+// any effect.
+func gcBgMarkDone() {
+ if cas(&work.bgMarkDone, 0, 1) {
+ // This is the first worker to reach completion.
+ // Signal the main GC goroutine.
+ lock(&work.bgMarkWake.lock)
+ if work.bgMarkWake.g == nil {
+ // It hasn't parked yet.
+ work.bgMarkWake.wake = true
+ } else {
+ ready(work.bgMarkWake.g, 0)
+ }
+ unlock(&work.bgMarkWake.lock)
+ }
+}
+
// gcMark runs the mark (or, for concurrent GC, mark termination)
// STW is in effect at this point.
//TODO go:nowritebarrier
// signal a completion point.
if xadd(&work.nwait, +1) == work.nproc && work.full == 0 && work.partial == 0 {
// This has reached a background completion
- // point. Is it the first this cycle?
- if cas(&work.bgMarkDone, 0, 1) {
- notewakeup(&work.bgMarkNote)
- }
+ // point.
+ gcBgMarkDone()
}
duration := nanotime() - startTime