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.
4
5// Garbage collector: sweeping
6
7// The sweeper consists of two different algorithms:
8//
9// * The object reclaimer finds and frees unmarked slots in spans. It
10//   can free a whole span if none of the objects are marked, but that
11//   isn't its goal. This can be driven either synchronously by
12//   mcentral.cacheSpan for mcentral spans, or asynchronously by
13//   sweepone from the list of all in-use spans in mheap_.sweepSpans.
14//
15// * The span reclaimer looks for spans that contain no marked objects
16//   and frees whole spans. This is a separate algorithm because
17//   freeing whole spans is the hardest task for the object reclaimer,
18//   but is critical when allocating new spans. The entry point for
19//   this is mheap_.reclaim and it's driven by a sequential scan of
20//   the page marks bitmap in the heap arenas.
21//
22// Both algorithms ultimately call mspan.sweep, which sweeps a single
23// heap span.
24
25package runtime
26
27import (
28	"runtime/internal/atomic"
29	"unsafe"
30)
31
32var sweep sweepdata
33
34// State of background sweep.
35type sweepdata struct {
36	lock    mutex
37	g       *g
38	parked  bool
39	started bool
40
41	nbgsweep    uint32
42	npausesweep uint32
43}
44
45// finishsweep_m ensures that all spans are swept.
46//
47// The world must be stopped. This ensures there are no sweeps in
48// progress.
49//
50//go:nowritebarrier
51func finishsweep_m() {
52	// Sweeping must be complete before marking commences, so
53	// sweep any unswept spans. If this is a concurrent GC, there
54	// shouldn't be any spans left to sweep, so this should finish
55	// instantly. If GC was forced before the concurrent sweep
56	// finished, there may be spans to sweep.
57	for sweepone() != ^uintptr(0) {
58		sweep.npausesweep++
59	}
60
61	nextMarkBitArenaEpoch()
62}
63
64func bgsweep(c chan int) {
65	setSystemGoroutine()
66
67	sweep.g = getg()
68
69	lock(&sweep.lock)
70	sweep.parked = true
71	c <- 1
72	goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1)
73
74	for {
75		for sweepone() != ^uintptr(0) {
76			sweep.nbgsweep++
77			Gosched()
78		}
79		for freeSomeWbufs(true) {
80			Gosched()
81		}
82		lock(&sweep.lock)
83		if !isSweepDone() {
84			// This can happen if a GC runs between
85			// gosweepone returning ^0 above
86			// and the lock being acquired.
87			unlock(&sweep.lock)
88			continue
89		}
90		sweep.parked = true
91		goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1)
92	}
93}
94
95// sweepone sweeps some unswept heap span and returns the number of pages returned
96// to the heap, or ^uintptr(0) if there was nothing to sweep.
97func sweepone() uintptr {
98	_g_ := getg()
99	sweepRatio := mheap_.sweepPagesPerByte // For debugging
100
101	// increment locks to ensure that the goroutine is not preempted
102	// in the middle of sweep thus leaving the span in an inconsistent state for next GC
103	_g_.m.locks++
104	if atomic.Load(&mheap_.sweepdone) != 0 {
105		_g_.m.locks--
106		return ^uintptr(0)
107	}
108	atomic.Xadd(&mheap_.sweepers, +1)
109
110	// Find a span to sweep.
111	var s *mspan
112	sg := mheap_.sweepgen
113	for {
114		s = mheap_.sweepSpans[1-sg/2%2].pop()
115		if s == nil {
116			atomic.Store(&mheap_.sweepdone, 1)
117			break
118		}
119		if state := s.state.get(); state != mSpanInUse {
120			// This can happen if direct sweeping already
121			// swept this span, but in that case the sweep
122			// generation should always be up-to-date.
123			if !(s.sweepgen == sg || s.sweepgen == sg+3) {
124				print("runtime: bad span s.state=", state, " s.sweepgen=", s.sweepgen, " sweepgen=", sg, "\n")
125				throw("non in-use span in unswept list")
126			}
127			continue
128		}
129		if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
130			break
131		}
132	}
133
134	// Sweep the span we found.
135	npages := ^uintptr(0)
136	if s != nil {
137		npages = s.npages
138		if s.sweep(false) {
139			// Whole span was freed. Count it toward the
140			// page reclaimer credit since these pages can
141			// now be used for span allocation.
142			atomic.Xadduintptr(&mheap_.reclaimCredit, npages)
143		} else {
144			// Span is still in-use, so this returned no
145			// pages to the heap and the span needs to
146			// move to the swept in-use list.
147			npages = 0
148		}
149	}
150
151	// Decrement the number of active sweepers and if this is the
152	// last one print trace information.
153	if atomic.Xadd(&mheap_.sweepers, -1) == 0 && atomic.Load(&mheap_.sweepdone) != 0 {
154		if debug.gcpacertrace > 0 {
155			print("pacer: sweep done at heap size ", memstats.heap_live>>20, "MB; allocated ", (memstats.heap_live-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept, " pages at ", sweepRatio, " pages/byte\n")
156		}
157	}
158	_g_.m.locks--
159	return npages
160}
161
162// isSweepDone reports whether all spans are swept or currently being swept.
163//
164// Note that this condition may transition from false to true at any
165// time as the sweeper runs. It may transition from true to false if a
166// GC runs; to prevent that the caller must be non-preemptible or must
167// somehow block GC progress.
168func isSweepDone() bool {
169	return mheap_.sweepdone != 0
170}
171
172// Returns only when span s has been swept.
173//go:nowritebarrier
174func (s *mspan) ensureSwept() {
175	// Caller must disable preemption.
176	// Otherwise when this function returns the span can become unswept again
177	// (if GC is triggered on another goroutine).
178	_g_ := getg()
179	if _g_.m.locks == 0 && _g_.m.mallocing == 0 && _g_ != _g_.m.g0 {
180		throw("mspan.ensureSwept: m is not locked")
181	}
182
183	sg := mheap_.sweepgen
184	spangen := atomic.Load(&s.sweepgen)
185	if spangen == sg || spangen == sg+3 {
186		return
187	}
188	// The caller must be sure that the span is a mSpanInUse span.
189	if atomic.Cas(&s.sweepgen, sg-2, sg-1) {
190		s.sweep(false)
191		return
192	}
193	// unfortunate condition, and we don't have efficient means to wait
194	for {
195		spangen := atomic.Load(&s.sweepgen)
196		if spangen == sg || spangen == sg+3 {
197			break
198		}
199		osyield()
200	}
201}
202
203// Sweep frees or collects finalizers for blocks not marked in the mark phase.
204// It clears the mark bits in preparation for the next GC round.
205// Returns true if the span was returned to heap.
206// If preserve=true, don't return it to heap nor relink in mcentral lists;
207// caller takes care of it.
208func (s *mspan) sweep(preserve bool) bool {
209	// It's critical that we enter this function with preemption disabled,
210	// GC must not start while we are in the middle of this function.
211	_g_ := getg()
212	if _g_.m.locks == 0 && _g_.m.mallocing == 0 && _g_ != _g_.m.g0 {
213		throw("mspan.sweep: m is not locked")
214	}
215	sweepgen := mheap_.sweepgen
216	if state := s.state.get(); state != mSpanInUse || s.sweepgen != sweepgen-1 {
217		print("mspan.sweep: state=", state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
218		throw("mspan.sweep: bad span state")
219	}
220
221	if trace.enabled {
222		traceGCSweepSpan(s.npages * _PageSize)
223	}
224
225	atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages))
226
227	spc := s.spanclass
228	size := s.elemsize
229	res := false
230
231	c := _g_.m.mcache
232	freeToHeap := false
233
234	// The allocBits indicate which unmarked objects don't need to be
235	// processed since they were free at the end of the last GC cycle
236	// and were not allocated since then.
237	// If the allocBits index is >= s.freeindex and the bit
238	// is not marked then the object remains unallocated
239	// since the last GC.
240	// This situation is analogous to being on a freelist.
241
242	// Unlink & free special records for any objects we're about to free.
243	// Two complications here:
244	// 1. An object can have both finalizer and profile special records.
245	//    In such case we need to queue finalizer for execution,
246	//    mark the object as live and preserve the profile special.
247	// 2. A tiny object can have several finalizers setup for different offsets.
248	//    If such object is not marked, we need to queue all finalizers at once.
249	// Both 1 and 2 are possible at the same time.
250	specialp := &s.specials
251	special := *specialp
252	for special != nil {
253		// A finalizer can be set for an inner byte of an object, find object beginning.
254		objIndex := uintptr(special.offset) / size
255		p := s.base() + objIndex*size
256		mbits := s.markBitsForIndex(objIndex)
257		if !mbits.isMarked() {
258			// This object is not marked and has at least one special record.
259			// Pass 1: see if it has at least one finalizer.
260			hasFin := false
261			endOffset := p - s.base() + size
262			for tmp := special; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next {
263				if tmp.kind == _KindSpecialFinalizer {
264					// Stop freeing of object if it has a finalizer.
265					mbits.setMarkedNonAtomic()
266					hasFin = true
267					break
268				}
269			}
270			// Pass 2: queue all finalizers _or_ handle profile record.
271			for special != nil && uintptr(special.offset) < endOffset {
272				// Find the exact byte for which the special was setup
273				// (as opposed to object beginning).
274				p := s.base() + uintptr(special.offset)
275				if special.kind == _KindSpecialFinalizer || !hasFin {
276					// Splice out special record.
277					y := special
278					special = special.next
279					*specialp = special
280					freespecial(y, unsafe.Pointer(p), size)
281				} else {
282					// This is profile record, but the object has finalizers (so kept alive).
283					// Keep special record.
284					specialp = &special.next
285					special = *specialp
286				}
287			}
288		} else {
289			// object is still live: keep special record
290			specialp = &special.next
291			special = *specialp
292		}
293	}
294
295	if debug.allocfreetrace != 0 || debug.clobberfree != 0 || raceenabled || msanenabled {
296		// Find all newly freed objects. This doesn't have to
297		// efficient; allocfreetrace has massive overhead.
298		mbits := s.markBitsForBase()
299		abits := s.allocBitsForIndex(0)
300		for i := uintptr(0); i < s.nelems; i++ {
301			if !mbits.isMarked() && (abits.index < s.freeindex || abits.isMarked()) {
302				x := s.base() + i*s.elemsize
303				if debug.allocfreetrace != 0 {
304					tracefree(unsafe.Pointer(x), size)
305				}
306				if debug.clobberfree != 0 {
307					clobberfree(unsafe.Pointer(x), size)
308				}
309				if raceenabled {
310					racefree(unsafe.Pointer(x), size)
311				}
312				if msanenabled {
313					msanfree(unsafe.Pointer(x), size)
314				}
315			}
316			mbits.advance()
317			abits.advance()
318		}
319	}
320
321	// Count the number of free objects in this span.
322	nalloc := uint16(s.countAlloc())
323	if spc.sizeclass() == 0 && nalloc == 0 {
324		s.needzero = 1
325		freeToHeap = true
326	}
327	nfreed := s.allocCount - nalloc
328	if nalloc > s.allocCount {
329		print("runtime: nelems=", s.nelems, " nalloc=", nalloc, " previous allocCount=", s.allocCount, " nfreed=", nfreed, "\n")
330		throw("sweep increased allocation count")
331	}
332
333	s.allocCount = nalloc
334	wasempty := s.nextFreeIndex() == s.nelems
335	s.freeindex = 0 // reset allocation index to start of span.
336	if trace.enabled {
337		getg().m.p.ptr().traceReclaimed += uintptr(nfreed) * s.elemsize
338	}
339
340	// gcmarkBits becomes the allocBits.
341	// get a fresh cleared gcmarkBits in preparation for next GC
342	s.allocBits = s.gcmarkBits
343	s.gcmarkBits = newMarkBits(s.nelems)
344
345	// Initialize alloc bits cache.
346	s.refillAllocCache(0)
347
348	// We need to set s.sweepgen = h.sweepgen only when all blocks are swept,
349	// because of the potential for a concurrent free/SetFinalizer.
350	// But we need to set it before we make the span available for allocation
351	// (return it to heap or mcentral), because allocation code assumes that a
352	// span is already swept if available for allocation.
353	if freeToHeap || nfreed == 0 {
354		// The span must be in our exclusive ownership until we update sweepgen,
355		// check for potential races.
356		if state := s.state.get(); state != mSpanInUse || s.sweepgen != sweepgen-1 {
357			print("mspan.sweep: state=", state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
358			throw("mspan.sweep: bad span state after sweep")
359		}
360		// Serialization point.
361		// At this point the mark bits are cleared and allocation ready
362		// to go so release the span.
363		atomic.Store(&s.sweepgen, sweepgen)
364	}
365
366	if nfreed > 0 && spc.sizeclass() != 0 {
367		c.local_nsmallfree[spc.sizeclass()] += uintptr(nfreed)
368		res = mheap_.central[spc].mcentral.freeSpan(s, preserve, wasempty)
369		// mcentral.freeSpan updates sweepgen
370	} else if freeToHeap {
371		// Free large span to heap
372
373		// NOTE(rsc,dvyukov): The original implementation of efence
374		// in CL 22060046 used sysFree instead of sysFault, so that
375		// the operating system would eventually give the memory
376		// back to us again, so that an efence program could run
377		// longer without running out of memory. Unfortunately,
378		// calling sysFree here without any kind of adjustment of the
379		// heap data structures means that when the memory does
380		// come back to us, we have the wrong metadata for it, either in
381		// the mspan structures or in the garbage collection bitmap.
382		// Using sysFault here means that the program will run out of
383		// memory fairly quickly in efence mode, but at least it won't
384		// have mysterious crashes due to confused memory reuse.
385		// It should be possible to switch back to sysFree if we also
386		// implement and then call some kind of mheap.deleteSpan.
387		if debug.efence > 0 {
388			s.limit = 0 // prevent mlookup from finding this span
389			sysFault(unsafe.Pointer(s.base()), size)
390		} else {
391			mheap_.freeSpan(s)
392		}
393		c.local_nlargefree++
394		c.local_largefree += size
395		res = true
396	}
397	if !res {
398		// The span has been swept and is still in-use, so put
399		// it on the swept in-use list.
400		mheap_.sweepSpans[sweepgen/2%2].push(s)
401	}
402	return res
403}
404
405// deductSweepCredit deducts sweep credit for allocating a span of
406// size spanBytes. This must be performed *before* the span is
407// allocated to ensure the system has enough credit. If necessary, it
408// performs sweeping to prevent going in to debt. If the caller will
409// also sweep pages (e.g., for a large allocation), it can pass a
410// non-zero callerSweepPages to leave that many pages unswept.
411//
412// deductSweepCredit makes a worst-case assumption that all spanBytes
413// bytes of the ultimately allocated span will be available for object
414// allocation.
415//
416// deductSweepCredit is the core of the "proportional sweep" system.
417// It uses statistics gathered by the garbage collector to perform
418// enough sweeping so that all pages are swept during the concurrent
419// sweep phase between GC cycles.
420//
421// mheap_ must NOT be locked.
422func deductSweepCredit(spanBytes uintptr, callerSweepPages uintptr) {
423	if mheap_.sweepPagesPerByte == 0 {
424		// Proportional sweep is done or disabled.
425		return
426	}
427
428	if trace.enabled {
429		traceGCSweepStart()
430	}
431
432retry:
433	sweptBasis := atomic.Load64(&mheap_.pagesSweptBasis)
434
435	// Fix debt if necessary.
436	newHeapLive := uintptr(atomic.Load64(&memstats.heap_live)-mheap_.sweepHeapLiveBasis) + spanBytes
437	pagesTarget := int64(mheap_.sweepPagesPerByte*float64(newHeapLive)) - int64(callerSweepPages)
438	for pagesTarget > int64(atomic.Load64(&mheap_.pagesSwept)-sweptBasis) {
439		if sweepone() == ^uintptr(0) {
440			mheap_.sweepPagesPerByte = 0
441			break
442		}
443		if atomic.Load64(&mheap_.pagesSweptBasis) != sweptBasis {
444			// Sweep pacing changed. Recompute debt.
445			goto retry
446		}
447	}
448
449	if trace.enabled {
450		traceGCSweepDone()
451	}
452}
453
454// clobberfree sets the memory content at x to bad content, for debugging
455// purposes.
456func clobberfree(x unsafe.Pointer, size uintptr) {
457	// size (span.elemsize) is always a multiple of 4.
458	for i := uintptr(0); i < size; i += 4 {
459		*(*uint32)(add(x, i)) = 0xdeadbeef
460	}
461}
462