deductSweepCredit(spanBytes, 0)
lock(&c.lock)
+ traceDone := false
+ if trace.enabled {
+ traceGCSweepStart()
+ }
sg := mheap_.sweepgen
retry:
var s *mspan
// all subsequent ones must also be either swept or in process of sweeping
break
}
+ if trace.enabled {
+ traceGCSweepDone()
+ traceDone = true
+ }
unlock(&c.lock)
// Replenish central list if empty.
// At this point s is a non-empty span, queued at the end of the empty list,
// c is unlocked.
havespan:
+ if trace.enabled && !traceDone {
+ traceGCSweepDone()
+ }
cap := int32((s.npages << _PageShift) / s.elemsize)
n := cap - int32(s.allocCount)
if n == 0 || s.freeindex == s.nelems || uintptr(s.allocCount) == s.nelems {
}
if trace.enabled {
- traceGCSweepStart()
+ traceGCSweepSpan()
}
atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages))
// it on the swept in-use list.
mheap_.sweepSpans[sweepgen/2%2].push(s)
}
- if trace.enabled {
- traceGCSweepDone()
- }
return res
}
return
}
+ if trace.enabled {
+ traceGCSweepStart()
+ }
+
// Account for this span allocation.
spanBytesAlloc := atomic.Xadd64(&mheap_.spanBytesAlloc, int64(spanBytes))
break
}
}
+
+ if trace.enabled {
+ traceGCSweepDone()
+ }
}
// reimburseSweepCredit records that unusableBytes bytes of a
// If GC kept a bit for whether there were any marks
// in a span, we could release these free spans
// at the end of GC and eliminate this entirely.
+ if trace.enabled {
+ traceGCSweepStart()
+ }
h.reclaim(npage)
+ if trace.enabled {
+ traceGCSweepDone()
+ }
}
// transfer stats from cache to global
tracebuf traceBufPtr
+ // traceSweep indicates the next traceGCSweepSpan should emit
+ // a sweep start event. This is used to defer the sweep start
+ // event until a span has actually been swept.
+ traceSweep bool
+
palloc persistentAlloc // per-P to avoid mutex
// Per-P GC state
traceEvent(traceEvGCScanDone, -1)
}
+// traceGCSweepStart prepares to trace a sweep loop. This does not
+// emit any events until traceGCSweepSpan is called.
+//
+// traceGCSweepStart must be paired with traceGCSweepDone and there
+// must be no preemption points between these two calls.
func traceGCSweepStart() {
- traceEvent(traceEvGCSweepStart, 1)
+ // Delay the actual GCSweepStart event until the first span
+ // sweep. If we don't sweep anything, don't emit any events.
+ _p_ := getg().m.p.ptr()
+ if _p_.traceSweep {
+ throw("double traceGCSweepStart")
+ }
+ _p_.traceSweep = true
+}
+
+// traceGCSweepSpan traces the sweep of a single page.
+//
+// This may be called outside a traceGCSweepStart/traceGCSweepDone
+// pair; however, it will not emit any trace events in this case.
+func traceGCSweepSpan() {
+ _p_ := getg().m.p.ptr()
+ if _p_.traceSweep {
+ traceEvent(traceEvGCSweepStart, 1)
+ _p_.traceSweep = false
+ }
}
func traceGCSweepDone() {
- traceEvent(traceEvGCSweepDone, -1)
+ _p_ := getg().m.p.ptr()
+ if !_p_.traceSweep {
+ traceEvent(traceEvGCSweepDone, -1)
+ }
+ _p_.traceSweep = false
}
func traceGCMarkAssistStart() {