* typeck2.c (cxx_incomplete_type_diagnostic): Revert change and
[official-gcc.git] / libgo / go / runtime / mgcsweep.go
blob2b698bf74a506dfcf404e4873a788ccb4b75b87a
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
7 package runtime
9 import (
10 "runtime/internal/atomic"
11 "unsafe"
14 var sweep sweepdata
16 // State of background sweep.
17 type sweepdata struct {
18 lock mutex
19 g *g
20 parked bool
21 started bool
23 nbgsweep uint32
24 npausesweep uint32
26 // pacertracegen is the sweepgen at which the last pacer trace
27 // "sweep finished" message was printed.
28 pacertracegen uint32
31 // finishsweep_m ensures that all spans are swept.
33 // The world must be stopped. This ensures there are no sweeps in
34 // progress.
36 //go:nowritebarrier
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) {
44 sweep.npausesweep++
47 nextMarkBitArenaEpoch()
50 func bgsweep(c chan int) {
51 setSystemGoroutine()
53 sweep.g = getg()
55 lock(&sweep.lock)
56 sweep.parked = true
57 c <- 1
58 goparkunlock(&sweep.lock, "GC sweep wait", traceEvGoBlock, 1)
60 for {
61 for gosweepone() != ^uintptr(0) {
62 sweep.nbgsweep++
63 Gosched()
65 lock(&sweep.lock)
66 if !gosweepdone() {
67 // This can happen if a GC runs between
68 // gosweepone returning ^0 above
69 // and the lock being acquired.
70 unlock(&sweep.lock)
71 continue
73 sweep.parked = true
74 goparkunlock(&sweep.lock, "GC sweep wait", traceEvGoBlock, 1)
78 // sweeps one span
79 // returns number of pages returned to heap, or ^uintptr(0) if there is nothing to sweep
80 //go:nowritebarrier
81 func sweepone() uintptr {
82 _g_ := getg()
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
86 _g_.m.locks++
87 sg := mheap_.sweepgen
88 for {
89 s := mheap_.sweepSpans[1-sg/2%2].pop()
90 if s == nil {
91 mheap_.sweepdone = 1
92 _g_.m.locks--
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")
96 return ^uintptr(0)
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")
106 continue
108 if s.sweepgen != sg-2 || !atomic.Cas(&s.sweepgen, sg-2, sg-1) {
109 continue
111 npages := s.npages
112 if !s.sweep(false) {
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.
116 npages = 0
118 _g_.m.locks--
119 return npages
123 //go:nowritebarrier
124 func gosweepone() uintptr {
125 var ret uintptr
126 systemstack(func() {
127 ret = sweepone()
129 return ret
132 //go:nowritebarrier
133 func gosweepdone() bool {
134 return mheap_.sweepdone != 0
137 // Returns only when span s has been swept.
138 //go:nowritebarrier
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).
143 _g_ := getg()
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 {
150 return
152 // The caller must be sure that the span is a MSpanInUse span.
153 if atomic.Cas(&s.sweepgen, sg-2, sg-1) {
154 s.sweep(false)
155 return
157 // unfortunate condition, and we don't have efficient means to wait
158 for atomic.Load(&s.sweepgen) != sg {
159 osyield()
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.
172 _g_ := getg()
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")
182 if trace.enabled {
183 traceGCSweepStart()
186 atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages))
188 cl := s.sizeclass
189 size := s.elemsize
190 res := false
191 nfree := 0
193 c := _g_.m.mcache
194 freeToHeap := false
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
213 special := *specialp
214 for special != nil {
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.
222 hasFin := false
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()
228 hasFin = true
229 break
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.
239 y := special
240 special = special.next
241 *specialp = special
242 freespecial(y, unsafe.Pointer(p), size)
243 } else {
244 // This is profile record, but the object has finalizers (so kept alive).
245 // Keep special record.
246 specialp = &special.next
247 special = *specialp
250 } else {
251 // object is still live: keep special record
252 specialp = &special.next
253 special = *specialp
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)
268 if raceenabled {
269 racefree(unsafe.Pointer(x), size)
271 if msanenabled {
272 msanfree(unsafe.Pointer(x), size)
275 mbits.advance()
276 abits.advance()
280 // Count the number of free objects in this span.
281 nfree = s.countFree()
282 if cl == 0 && nfree != 0 {
283 s.needzero = 1
284 freeToHeap = true
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)
361 } else {
362 mheap_.freeSpan(s, 1)
364 c.local_nlargefree++
365 c.local_largefree += size
366 res = true
368 if !res {
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)
373 if trace.enabled {
374 traceGCSweepDone()
376 return res
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.
400 return
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
411 break
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.
422 return
424 nval := atomic.Xadd64(&mheap_.spanBytesAlloc, -int64(unusableBytes))
425 if int64(nval) < 0 {
426 // Debugging for #18043.
427 print("runtime: bad spanBytesAlloc=", nval, " (was ", nval+uint64(unusableBytes), ") unusableBytes=", unusableBytes, " sweepPagesPerByte=", mheap_.sweepPagesPerByte, "\n")
428 throw("spanBytesAlloc underflow")