1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Garbage collector: sweeping
10 "runtime/internal/atomic"
16 // State of background sweep.
17 type sweepdata
struct {
26 // pacertracegen is the sweepgen at which the last pacer trace
27 // "sweep finished" message was printed.
31 // finishsweep_m ensures that all spans are swept.
33 // The world must be stopped. This ensures there are no sweeps in
37 func finishsweep_m() {
38 // Sweeping must be complete before marking commences, so
39 // sweep any unswept spans. If this is a concurrent GC, there
40 // shouldn't be any spans left to sweep, so this should finish
41 // instantly. If GC was forced before the concurrent sweep
42 // finished, there may be spans to sweep.
43 for sweepone() != ^uintptr(0) {
47 nextMarkBitArenaEpoch()
50 func bgsweep(c
chan int) {
58 goparkunlock(&sweep
.lock
, "GC sweep wait", traceEvGoBlock
, 1)
61 for gosweepone() != ^uintptr(0) {
67 // This can happen if a GC runs between
68 // gosweepone returning ^0 above
69 // and the lock being acquired.
74 goparkunlock(&sweep
.lock
, "GC sweep wait", traceEvGoBlock
, 1)
79 // returns number of pages returned to heap, or ^uintptr(0) if there is nothing to sweep
81 func sweepone() uintptr {
84 // increment locks to ensure that the goroutine is not preempted
85 // in the middle of sweep thus leaving the span in an inconsistent state for next GC
89 s
:= mheap_
.sweepSpans
[1-sg
/2%2
].pop()
93 if debug
.gcpacertrace
> 0 && atomic
.Cas(&sweep
.pacertracegen
, sg
-2, sg
) {
94 print("pacer: sweep done at heap size ", memstats
.heap_live
>>20, "MB; allocated ", mheap_
.spanBytesAlloc
>>20, "MB of spans; swept ", mheap_
.pagesSwept
, " pages at ", mheap_
.sweepPagesPerByte
, " pages/byte\n")
98 if s
.state
!= mSpanInUse
{
99 // This can happen if direct sweeping already
100 // swept this span, but in that case the sweep
101 // generation should always be up-to-date.
102 if s
.sweepgen
!= sg
{
103 print("runtime: bad span s.state=", s
.state
, " s.sweepgen=", s
.sweepgen
, " sweepgen=", sg
, "\n")
104 throw("non in-use span in unswept list")
108 if s
.sweepgen
!= sg
-2 ||
!atomic
.Cas(&s
.sweepgen
, sg
-2, sg
-1) {
113 // Span is still in-use, so this returned no
114 // pages to the heap and the span needs to
115 // move to the swept in-use list.
124 func gosweepone() uintptr {
133 func gosweepdone() bool {
134 return mheap_
.sweepdone
!= 0
137 // Returns only when span s has been swept.
139 func (s
*mspan
) ensureSwept() {
140 // Caller must disable preemption.
141 // Otherwise when this function returns the span can become unswept again
142 // (if GC is triggered on another goroutine).
144 if _g_
.m
.locks
== 0 && _g_
.m
.mallocing
== 0 && _g_
!= _g_
.m
.g0
{
145 throw("MSpan_EnsureSwept: m is not locked")
148 sg
:= mheap_
.sweepgen
149 if atomic
.Load(&s
.sweepgen
) == sg
{
152 // The caller must be sure that the span is a MSpanInUse span.
153 if atomic
.Cas(&s
.sweepgen
, sg
-2, sg
-1) {
157 // unfortunate condition, and we don't have efficient means to wait
158 for atomic
.Load(&s
.sweepgen
) != sg
{
163 // Sweep frees or collects finalizers for blocks not marked in the mark phase.
164 // It clears the mark bits in preparation for the next GC round.
165 // Returns true if the span was returned to heap.
166 // If preserve=true, don't return it to heap nor relink in MCentral lists;
167 // caller takes care of it.
168 //TODO go:nowritebarrier
169 func (s
*mspan
) sweep(preserve
bool) bool {
170 // It's critical that we enter this function with preemption disabled,
171 // GC must not start while we are in the middle of this function.
173 if _g_
.m
.locks
== 0 && _g_
.m
.mallocing
== 0 && _g_
!= _g_
.m
.g0
{
174 throw("MSpan_Sweep: m is not locked")
176 sweepgen
:= mheap_
.sweepgen
177 if s
.state
!= mSpanInUse || s
.sweepgen
!= sweepgen
-1 {
178 print("MSpan_Sweep: state=", s
.state
, " sweepgen=", s
.sweepgen
, " mheap.sweepgen=", sweepgen
, "\n")
179 throw("MSpan_Sweep: bad span state")
186 atomic
.Xadd64(&mheap_
.pagesSwept
, int64(s
.npages
))
196 // The allocBits indicate which unmarked objects don't need to be
197 // processed since they were free at the end of the last GC cycle
198 // and were not allocated since then.
199 // If the allocBits index is >= s.freeindex and the bit
200 // is not marked then the object remains unallocated
201 // since the last GC.
202 // This situation is analogous to being on a freelist.
204 // Unlink & free special records for any objects we're about to free.
205 // Two complications here:
206 // 1. An object can have both finalizer and profile special records.
207 // In such case we need to queue finalizer for execution,
208 // mark the object as live and preserve the profile special.
209 // 2. A tiny object can have several finalizers setup for different offsets.
210 // If such object is not marked, we need to queue all finalizers at once.
211 // Both 1 and 2 are possible at the same time.
212 specialp
:= &s
.specials
215 // A finalizer can be set for an inner byte of an object, find object beginning.
216 objIndex
:= uintptr(special
.offset
) / size
217 p
:= s
.base() + objIndex
*size
218 mbits
:= s
.markBitsForIndex(objIndex
)
219 if !mbits
.isMarked() {
220 // This object is not marked and has at least one special record.
221 // Pass 1: see if it has at least one finalizer.
223 endOffset
:= p
- s
.base() + size
224 for tmp
:= special
; tmp
!= nil && uintptr(tmp
.offset
) < endOffset
; tmp
= tmp
.next
{
225 if tmp
.kind
== _KindSpecialFinalizer
{
226 // Stop freeing of object if it has a finalizer.
227 mbits
.setMarkedNonAtomic()
232 // Pass 2: queue all finalizers _or_ handle profile record.
233 for special
!= nil && uintptr(special
.offset
) < endOffset
{
234 // Find the exact byte for which the special was setup
235 // (as opposed to object beginning).
236 p
:= s
.base() + uintptr(special
.offset
)
237 if special
.kind
== _KindSpecialFinalizer ||
!hasFin
{
238 // Splice out special record.
240 special
= special
.next
242 freespecial(y
, unsafe
.Pointer(p
), size
)
244 // This is profile record, but the object has finalizers (so kept alive).
245 // Keep special record.
246 specialp
= &special
.next
251 // object is still live: keep special record
252 specialp
= &special
.next
257 if debug
.allocfreetrace
!= 0 || raceenabled || msanenabled
{
258 // Find all newly freed objects. This doesn't have to
259 // efficient; allocfreetrace has massive overhead.
260 mbits
:= s
.markBitsForBase()
261 abits
:= s
.allocBitsForIndex(0)
262 for i
:= uintptr(0); i
< s
.nelems
; i
++ {
263 if !mbits
.isMarked() && (abits
.index
< s
.freeindex || abits
.isMarked()) {
264 x
:= s
.base() + i
*s
.elemsize
265 if debug
.allocfreetrace
!= 0 {
266 tracefree(unsafe
.Pointer(x
), size
)
269 racefree(unsafe
.Pointer(x
), size
)
272 msanfree(unsafe
.Pointer(x
), size
)
280 // Count the number of free objects in this span.
281 nfree
= s
.countFree()
282 if cl
== 0 && nfree
!= 0 {
286 nalloc
:= uint16(s
.nelems
) - uint16(nfree
)
287 nfreed
:= s
.allocCount
- nalloc
289 // This test is not reliable with gccgo, because of
290 // conservative stack scanning. The test boils down to
291 // checking that no new bits have been set in gcmarkBits since
292 // the span was added to the sweep count. New bits are set by
293 // greyobject. Seeing a new bit means that a live pointer has
294 // appeared that was not found during the mark phase. That can
295 // not happen when pointers are followed strictly. However,
296 // with conservative checking, it is possible for a pointer
297 // that will never be used to appear live and to cause a mark
298 // to be added. That is unfortunate in that it causes this
299 // check to be inaccurate, and it will keep an object live
300 // unnecessarily, but provided the pointer is not really live
301 // it is not otherwise a problem. So we disable the test for gccgo.
302 if false && nalloc
> s
.allocCount
{
303 print("runtime: nelems=", s
.nelems
, " nfree=", nfree
, " nalloc=", nalloc
, " previous allocCount=", s
.allocCount
, " nfreed=", nfreed
, "\n")
304 throw("sweep increased allocation count")
307 s
.allocCount
= nalloc
308 wasempty
:= s
.nextFreeIndex() == s
.nelems
309 s
.freeindex
= 0 // reset allocation index to start of span.
311 // gcmarkBits becomes the allocBits.
312 // get a fresh cleared gcmarkBits in preparation for next GC
313 s
.allocBits
= s
.gcmarkBits
314 s
.gcmarkBits
= newMarkBits(s
.nelems
)
316 // Initialize alloc bits cache.
317 s
.refillAllocCache(0)
319 // We need to set s.sweepgen = h.sweepgen only when all blocks are swept,
320 // because of the potential for a concurrent free/SetFinalizer.
321 // But we need to set it before we make the span available for allocation
322 // (return it to heap or mcentral), because allocation code assumes that a
323 // span is already swept if available for allocation.
324 if freeToHeap || nfreed
== 0 {
325 // The span must be in our exclusive ownership until we update sweepgen,
326 // check for potential races.
327 if s
.state
!= mSpanInUse || s
.sweepgen
!= sweepgen
-1 {
328 print("MSpan_Sweep: state=", s
.state
, " sweepgen=", s
.sweepgen
, " mheap.sweepgen=", sweepgen
, "\n")
329 throw("MSpan_Sweep: bad span state after sweep")
331 // Serialization point.
332 // At this point the mark bits are cleared and allocation ready
333 // to go so release the span.
334 atomic
.Store(&s
.sweepgen
, sweepgen
)
337 if nfreed
> 0 && cl
!= 0 {
338 c
.local_nsmallfree
[cl
] += uintptr(nfreed
)
339 res
= mheap_
.central
[cl
].mcentral
.freeSpan(s
, preserve
, wasempty
)
340 // MCentral_FreeSpan updates sweepgen
341 } else if freeToHeap
{
342 // Free large span to heap
344 // NOTE(rsc,dvyukov): The original implementation of efence
345 // in CL 22060046 used SysFree instead of SysFault, so that
346 // the operating system would eventually give the memory
347 // back to us again, so that an efence program could run
348 // longer without running out of memory. Unfortunately,
349 // calling SysFree here without any kind of adjustment of the
350 // heap data structures means that when the memory does
351 // come back to us, we have the wrong metadata for it, either in
352 // the MSpan structures or in the garbage collection bitmap.
353 // Using SysFault here means that the program will run out of
354 // memory fairly quickly in efence mode, but at least it won't
355 // have mysterious crashes due to confused memory reuse.
356 // It should be possible to switch back to SysFree if we also
357 // implement and then call some kind of MHeap_DeleteSpan.
358 if debug
.efence
> 0 {
359 s
.limit
= 0 // prevent mlookup from finding this span
360 sysFault(unsafe
.Pointer(s
.base()), size
)
362 mheap_
.freeSpan(s
, 1)
365 c
.local_largefree
+= size
369 // The span has been swept and is still in-use, so put
370 // it on the swept in-use list.
371 mheap_
.sweepSpans
[sweepgen
/2%2
].push(s
)
379 // deductSweepCredit deducts sweep credit for allocating a span of
380 // size spanBytes. This must be performed *before* the span is
381 // allocated to ensure the system has enough credit. If necessary, it
382 // performs sweeping to prevent going in to debt. If the caller will
383 // also sweep pages (e.g., for a large allocation), it can pass a
384 // non-zero callerSweepPages to leave that many pages unswept.
386 // deductSweepCredit makes a worst-case assumption that all spanBytes
387 // bytes of the ultimately allocated span will be available for object
388 // allocation. The caller should call reimburseSweepCredit if that
389 // turns out not to be the case once the span is allocated.
391 // deductSweepCredit is the core of the "proportional sweep" system.
392 // It uses statistics gathered by the garbage collector to perform
393 // enough sweeping so that all pages are swept during the concurrent
394 // sweep phase between GC cycles.
396 // mheap_ must NOT be locked.
397 func deductSweepCredit(spanBytes
uintptr, callerSweepPages
uintptr) {
398 if mheap_
.sweepPagesPerByte
== 0 {
399 // Proportional sweep is done or disabled.
403 // Account for this span allocation.
404 spanBytesAlloc
:= atomic
.Xadd64(&mheap_
.spanBytesAlloc
, int64(spanBytes
))
406 // Fix debt if necessary.
407 pagesOwed
:= int64(mheap_
.sweepPagesPerByte
* float64(spanBytesAlloc
))
408 for pagesOwed
-int64(atomic
.Load64(&mheap_
.pagesSwept
)) > int64(callerSweepPages
) {
409 if gosweepone() == ^uintptr(0) {
410 mheap_
.sweepPagesPerByte
= 0
416 // reimburseSweepCredit records that unusableBytes bytes of a
417 // just-allocated span are not available for object allocation. This
418 // offsets the worst-case charge performed by deductSweepCredit.
419 func reimburseSweepCredit(unusableBytes
uintptr) {
420 if mheap_
.sweepPagesPerByte
== 0 {
421 // Nobody cares about the credit. Avoid the atomic.
424 nval
:= atomic
.Xadd64(&mheap_
.spanBytesAlloc
, -int64(unusableBytes
))
426 // Debugging for #18043.
427 print("runtime: bad spanBytesAlloc=", nval
, " (was ", nval
+uint64(unusableBytes
), ") unusableBytes=", unusableBytes
, " sweepPagesPerByte=", mheap_
.sweepPagesPerByte
, "\n")
428 throw("spanBytesAlloc underflow")