blob: 2d0cbd203c219f10348a2e6a8aecf74b9ccf6d25 [file] [log] [blame]
Russ Cox484f8012015-02-19 13:38:46 -05001// 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: marking and scanning
6
7package runtime
8
Michael Matloob67faca72015-11-02 14:09:24 -05009import (
10 "runtime/internal/atomic"
Michael Matloob432cb662015-11-11 12:39:30 -050011 "runtime/internal/sys"
Michael Matloob67faca72015-11-02 14:09:24 -050012 "unsafe"
13)
Russ Cox484f8012015-02-19 13:38:46 -050014
Austin Clementsd3df04c2015-10-16 16:52:26 -040015const (
16 fixedRootFinalizers = iota
17 fixedRootFlushCaches
Austin Clementse8337492016-03-11 17:00:46 -050018 fixedRootFreeGStacks
Austin Clementsd3df04c2015-10-16 16:52:26 -040019 fixedRootCount
20
21 // rootBlockBytes is the number of bytes to scan per data or
22 // BSS root.
23 rootBlockBytes = 256 << 10
24
25 // rootBlockSpans is the number of spans to scan per span
26 // root.
27 rootBlockSpans = 8 * 1024 // 64MB worth of spans
28)
29
Austin Clements82d14d72015-10-19 13:46:32 -040030// gcMarkRootPrepare queues root scanning jobs (stacks, globals, and
31// some miscellany) and initializes scanning-related state.
Austin Clementsd3df04c2015-10-16 16:52:26 -040032//
33// The caller must have call gcCopySpans().
34//
Austin Clements2a889b92016-03-04 11:58:26 -050035// The world must be stopped.
36//
Austin Clementsd3df04c2015-10-16 16:52:26 -040037//go:nowritebarrier
Austin Clements82d14d72015-10-19 13:46:32 -040038func gcMarkRootPrepare() {
Austin Clementsd3df04c2015-10-16 16:52:26 -040039 // Compute how many data and BSS root blocks there are.
40 nBlocks := func(bytes uintptr) int {
41 return int((bytes + rootBlockBytes - 1) / rootBlockBytes)
42 }
43
44 work.nDataRoots = 0
Austin Clementsd3df04c2015-10-16 16:52:26 -040045 work.nBSSRoots = 0
Austin Clementsb49b71a2016-03-18 11:27:59 -040046
47 // Only scan globals once per cycle; preferably concurrently.
48 if !work.markrootDone {
49 for datap := &firstmoduledata; datap != nil; datap = datap.next {
50 nDataRoots := nBlocks(datap.edata - datap.data)
51 if nDataRoots > work.nDataRoots {
52 work.nDataRoots = nDataRoots
53 }
54 }
55
56 for datap := &firstmoduledata; datap != nil; datap = datap.next {
57 nBSSRoots := nBlocks(datap.ebss - datap.bss)
58 if nBSSRoots > work.nBSSRoots {
59 work.nBSSRoots = nBSSRoots
60 }
Austin Clementsd3df04c2015-10-16 16:52:26 -040061 }
62 }
63
Austin Clementsefb0c552016-03-11 13:54:55 -050064 if !work.markrootDone {
65 // On the first markroot, we need to scan span roots.
66 // In concurrent GC, this happens during concurrent
67 // mark and we depend on addfinalizer to ensure the
68 // above invariants for objects that get finalizers
69 // after concurrent mark. In STW GC, this will happen
70 // during mark termination.
71 work.nSpanRoots = (len(work.spans) + rootBlockSpans - 1) / rootBlockSpans
Austin Clementsd3df04c2015-10-16 16:52:26 -040072
Austin Clements2a889b92016-03-04 11:58:26 -050073 // On the first markroot, we need to scan all Gs. Gs
74 // may be created after this point, but it's okay that
75 // we ignore them because they begin life without any
76 // roots, so there's nothing to scan, and any roots
77 // they create during the concurrent phase will be
78 // scanned during mark termination. During mark
79 // termination, allglen isn't changing, so we'll scan
80 // all Gs.
81 work.nStackRoots = int(atomic.Loaduintptr(&allglen))
82 work.nRescanRoots = 0
Austin Clementsefb0c552016-03-11 13:54:55 -050083 } else {
84 // We've already scanned span roots and kept the scan
85 // up-to-date during concurrent mark.
86 work.nSpanRoots = 0
Austin Clements2a889b92016-03-04 11:58:26 -050087
88 // On the second pass of markroot, we're just scanning
89 // dirty stacks. It's safe to access rescan since the
90 // world is stopped.
91 work.nStackRoots = 0
92 work.nRescanRoots = len(work.rescan.list)
Austin Clementsefb0c552016-03-11 13:54:55 -050093 }
Austin Clementsd3df04c2015-10-16 16:52:26 -040094
Austin Clements82d14d72015-10-19 13:46:32 -040095 work.markrootNext = 0
Austin Clements2a889b92016-03-04 11:58:26 -050096 work.markrootJobs = uint32(fixedRootCount + work.nDataRoots + work.nBSSRoots + work.nSpanRoots + work.nStackRoots + work.nRescanRoots)
Austin Clementsd3df04c2015-10-16 16:52:26 -040097}
98
Austin Clements82d14d72015-10-19 13:46:32 -040099// gcMarkRootCheck checks that all roots have been scanned. It is
100// purely for debugging.
101func gcMarkRootCheck() {
102 if work.markrootNext < work.markrootJobs {
103 print(work.markrootNext, " of ", work.markrootJobs, " markroot jobs done\n")
104 throw("left over markroot jobs")
105 }
Russ Cox484f8012015-02-19 13:38:46 -0500106
107 lock(&allglock)
Austin Clements2a889b92016-03-04 11:58:26 -0500108 // Check that stacks have been scanned.
109 if gcphase == _GCmarktermination {
110 for i := 0; i < len(allgs); i++ {
111 gp := allgs[i]
112 if !(gp.gcscandone && gp.gcscanvalid) && readgstatus(gp) != _Gdead {
113 println("gp", gp, "goid", gp.goid,
114 "status", readgstatus(gp),
115 "gcscandone", gp.gcscandone,
116 "gcscanvalid", gp.gcscanvalid)
117 throw("scan missed a g")
118 }
119 }
120 } else {
121 for i := 0; i < work.nStackRoots; i++ {
122 gp := allgs[i]
123 if !gp.gcscandone {
124 throw("scan missed a g")
125 }
Russ Cox484f8012015-02-19 13:38:46 -0500126 }
127 }
128 unlock(&allglock)
Russ Cox484f8012015-02-19 13:38:46 -0500129}
130
131// ptrmask for an allocation containing a single pointer.
Russ Cox4d0f3a12015-04-27 22:45:57 -0400132var oneptrmask = [...]uint8{1}
Russ Cox484f8012015-02-19 13:38:46 -0500133
Austin Clements82d14d72015-10-19 13:46:32 -0400134// markroot scans the i'th root.
135//
136// Preemption must be disabled (because this uses a gcWork).
137//
Austin Clements2a889b92016-03-04 11:58:26 -0500138// nowritebarrier is only advisory here.
139//
Russ Cox484f8012015-02-19 13:38:46 -0500140//go:nowritebarrier
Austin Clements7b229002015-11-23 18:44:03 -0500141func markroot(gcw *gcWork, i uint32) {
Austin Clements2a889b92016-03-04 11:58:26 -0500142 // TODO(austin): This is a bit ridiculous. Compute and store
143 // the bases in gcMarkRootPrepare instead of the counts.
Austin Clementsd3df04c2015-10-16 16:52:26 -0400144 baseData := uint32(fixedRootCount)
145 baseBSS := baseData + uint32(work.nDataRoots)
146 baseSpans := baseBSS + uint32(work.nBSSRoots)
147 baseStacks := baseSpans + uint32(work.nSpanRoots)
Austin Clements2a889b92016-03-04 11:58:26 -0500148 baseRescan := baseStacks + uint32(work.nStackRoots)
149 end := baseRescan + uint32(work.nRescanRoots)
Austin Clementsd3df04c2015-10-16 16:52:26 -0400150
Keith Randallcd5b1442015-03-11 12:58:47 -0700151 // Note: if you add a case here, please also update heapdump.go:dumproots.
Austin Clementsd3df04c2015-10-16 16:52:26 -0400152 switch {
153 case baseData <= i && i < baseBSS:
Michael Hudson-Doylea1f57592015-04-07 12:55:02 +1200154 for datap := &firstmoduledata; datap != nil; datap = datap.next {
Austin Clements7b229002015-11-23 18:44:03 -0500155 markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, gcw, int(i-baseData))
Michael Hudson-Doylefae4a122015-03-29 21:59:00 +0000156 }
Russ Cox484f8012015-02-19 13:38:46 -0500157
Austin Clementsd3df04c2015-10-16 16:52:26 -0400158 case baseBSS <= i && i < baseSpans:
Michael Hudson-Doylea1f57592015-04-07 12:55:02 +1200159 for datap := &firstmoduledata; datap != nil; datap = datap.next {
Austin Clements7b229002015-11-23 18:44:03 -0500160 markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, gcw, int(i-baseBSS))
Michael Hudson-Doylefae4a122015-03-29 21:59:00 +0000161 }
Russ Cox484f8012015-02-19 13:38:46 -0500162
Austin Clementsd3df04c2015-10-16 16:52:26 -0400163 case i == fixedRootFinalizers:
Russ Cox484f8012015-02-19 13:38:46 -0500164 for fb := allfin; fb != nil; fb = fb.alllink {
Austin Clements7b229002015-11-23 18:44:03 -0500165 scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), uintptr(fb.cnt)*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], gcw)
Russ Cox484f8012015-02-19 13:38:46 -0500166 }
167
Austin Clementsd3df04c2015-10-16 16:52:26 -0400168 case i == fixedRootFlushCaches:
Austin Clements82d14d72015-10-19 13:46:32 -0400169 if gcphase == _GCmarktermination { // Do not flush mcaches during concurrent phase.
Russ Cox484f8012015-02-19 13:38:46 -0500170 flushallmcaches()
171 }
172
Austin Clementse8337492016-03-11 17:00:46 -0500173 case i == fixedRootFreeGStacks:
174 // Only do this once per GC cycle; preferably
175 // concurrently.
176 if !work.markrootDone {
177 markrootFreeGStacks()
178 }
179
Austin Clementsd3df04c2015-10-16 16:52:26 -0400180 case baseSpans <= i && i < baseStacks:
181 // mark MSpan.specials
Austin Clements7b229002015-11-23 18:44:03 -0500182 markrootSpans(gcw, int(i-baseSpans))
Austin Clements572f08a2015-08-04 10:45:29 -0400183
Austin Clementsd3df04c2015-10-16 16:52:26 -0400184 default:
Russ Cox484f8012015-02-19 13:38:46 -0500185 // the rest is scanning goroutine stacks
Austin Clements2a889b92016-03-04 11:58:26 -0500186 var gp *g
187 if baseStacks <= i && i < baseRescan {
188 gp = allgs[i-baseStacks]
189 } else if baseRescan <= i && i < end {
190 gp = work.rescan.list[i-baseRescan].ptr()
191 } else {
Russ Cox484f8012015-02-19 13:38:46 -0500192 throw("markroot: bad index")
193 }
Russ Cox484f8012015-02-19 13:38:46 -0500194
195 // remember when we've first observed the G blocked
196 // needed only to output in traceback
197 status := readgstatus(gp) // We are not in a scan state
198 if (status == _Gwaiting || status == _Gsyscall) && gp.waitsince == 0 {
199 gp.waitsince = work.tstart
200 }
201
Austin Clements2a889b92016-03-04 11:58:26 -0500202 if gcphase != _GCmarktermination && gp.startpc == gcBgMarkWorkerPC && readgstatus(gp) != _Gdead {
Austin Clements82d14d72015-10-19 13:46:32 -0400203 // GC background workers may be
204 // non-preemptible, so we may deadlock if we
205 // try to scan them during a concurrent phase.
206 // They also have tiny stacks, so just ignore
207 // them until mark termination.
208 gp.gcscandone = true
Austin Clements2a889b92016-03-04 11:58:26 -0500209 queueRescan(gp)
Austin Clements82d14d72015-10-19 13:46:32 -0400210 break
211 }
212
213 // scang must be done on the system stack in case
214 // we're trying to scan our own stack.
215 systemstack(func() {
216 // If this is a self-scan, put the user G in
217 // _Gwaiting to prevent self-deadlock. It may
218 // already be in _Gwaiting if this is mark
219 // termination.
220 userG := getg().m.curg
221 selfScan := gp == userG && readgstatus(userG) == _Grunning
222 if selfScan {
223 casgstatus(userG, _Grunning, _Gwaiting)
224 userG.waitreason = "garbage collection scan"
225 }
226
227 // TODO: scang blocks until gp's stack has
228 // been scanned, which may take a while for
229 // running goroutines. Consider doing this in
230 // two phases where the first is non-blocking:
231 // we scan the stacks we can and ask running
232 // goroutines to scan themselves; and the
233 // second blocks.
Austin Clements3be48b42016-05-23 22:14:53 -0400234 scang(gp, gcw)
Austin Clements82d14d72015-10-19 13:46:32 -0400235
236 if selfScan {
237 casgstatus(userG, _Gwaiting, _Grunning)
238 }
239 })
Russ Cox484f8012015-02-19 13:38:46 -0500240 }
Russ Cox484f8012015-02-19 13:38:46 -0500241}
242
Austin Clementsd3df04c2015-10-16 16:52:26 -0400243// markrootBlock scans the shard'th shard of the block of memory [b0,
244// b0+n0), with the given pointer mask.
245//
246//go:nowritebarrier
247func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) {
Michael Matloob432cb662015-11-11 12:39:30 -0500248 if rootBlockBytes%(8*sys.PtrSize) != 0 {
Austin Clementsd3df04c2015-10-16 16:52:26 -0400249 // This is necessary to pick byte offsets in ptrmask0.
250 throw("rootBlockBytes must be a multiple of 8*ptrSize")
251 }
252
253 b := b0 + uintptr(shard)*rootBlockBytes
254 if b >= b0+n0 {
255 return
256 }
Michael Matloob432cb662015-11-11 12:39:30 -0500257 ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*sys.PtrSize))))
Austin Clementsd3df04c2015-10-16 16:52:26 -0400258 n := uintptr(rootBlockBytes)
259 if b+n > b0+n0 {
260 n = b0 + n0 - b
261 }
262
263 // Scan this shard.
264 scanblock(b, n, ptrmask, gcw)
265}
266
Austin Clementse8337492016-03-11 17:00:46 -0500267// markrootFreeGStacks frees stacks of dead Gs.
268//
269// This does not free stacks of dead Gs cached on Ps, but having a few
270// cached stacks around isn't a problem.
271//
272//TODO go:nowritebarrier
273func markrootFreeGStacks() {
274 // Take list of dead Gs with stacks.
275 lock(&sched.gflock)
276 list := sched.gfreeStack
277 sched.gfreeStack = nil
278 unlock(&sched.gflock)
279 if list == nil {
280 return
281 }
282
283 // Free stacks.
284 tail := list
285 for gp := list; gp != nil; gp = gp.schedlink.ptr() {
286 shrinkstack(gp)
287 tail = gp
288 }
289
290 // Put Gs back on the free list.
291 lock(&sched.gflock)
292 tail.schedlink.set(sched.gfreeNoStack)
293 sched.gfreeNoStack = list
294 unlock(&sched.gflock)
295}
296
Austin Clementsd3df04c2015-10-16 16:52:26 -0400297// markrootSpans marks roots for one shard of work.spans.
Austin Clements572f08a2015-08-04 10:45:29 -0400298//
299//go:nowritebarrier
300func markrootSpans(gcw *gcWork, shard int) {
Austin Clements608c1b02015-09-24 14:39:27 -0400301 // Objects with finalizers have two GC-related invariants:
302 //
303 // 1) Everything reachable from the object must be marked.
304 // This ensures that when we pass the object to its finalizer,
305 // everything the finalizer can reach will be retained.
306 //
307 // 2) Finalizer specials (which are not in the garbage
308 // collected heap) are roots. In practice, this means the fn
309 // field must be scanned.
310 //
311 // TODO(austin): There are several ideas for making this more
312 // efficient in issue #11485.
313
Austin Clementsc14d25c2016-02-15 18:24:06 -0500314 if work.markrootDone {
Austin Clementsefb0c552016-03-11 13:54:55 -0500315 throw("markrootSpans during second markroot")
Austin Clements608c1b02015-09-24 14:39:27 -0400316 }
317
Austin Clements572f08a2015-08-04 10:45:29 -0400318 sg := mheap_.sweepgen
Austin Clementsd3df04c2015-10-16 16:52:26 -0400319 startSpan := shard * rootBlockSpans
320 endSpan := (shard + 1) * rootBlockSpans
321 if endSpan > len(work.spans) {
322 endSpan = len(work.spans)
323 }
Austin Clements608c1b02015-09-24 14:39:27 -0400324 // Note that work.spans may not include spans that were
325 // allocated between entering the scan phase and now. This is
326 // okay because any objects with finalizers in those spans
327 // must have been allocated and given finalizers after we
328 // entered the scan phase, so addfinalizer will have ensured
329 // the above invariants for them.
Austin Clements4ac40852015-09-14 14:28:09 -0400330 for _, s := range work.spans[startSpan:endSpan] {
Austin Clements572f08a2015-08-04 10:45:29 -0400331 if s.state != mSpanInUse {
332 continue
333 }
334 if !useCheckmark && s.sweepgen != sg {
335 // sweepgen was updated (+2) during non-checkmark GC pass
336 print("sweep ", s.sweepgen, " ", sg, "\n")
337 throw("gc: unswept span")
338 }
Austin Clements608c1b02015-09-24 14:39:27 -0400339
340 // Speculatively check if there are any specials
341 // without acquiring the span lock. This may race with
342 // adding the first special to a span, but in that
343 // case addfinalizer will observe that the GC is
344 // active (which is globally synchronized) and ensure
345 // the above invariants. We may also ensure the
346 // invariants, but it's okay to scan an object twice.
347 if s.specials == nil {
348 continue
349 }
350
351 // Lock the specials to prevent a special from being
352 // removed from the list while we're traversing it.
353 lock(&s.speciallock)
354
Austin Clements572f08a2015-08-04 10:45:29 -0400355 for sp := s.specials; sp != nil; sp = sp.next {
356 if sp.kind != _KindSpecialFinalizer {
357 continue
358 }
359 // don't mark finalized object, but scan it so we
360 // retain everything it points to.
361 spf := (*specialfinalizer)(unsafe.Pointer(sp))
362 // A finalizer can be set for an inner byte of an object, find object beginning.
Rick Hudsonf8d0d4f2016-03-14 12:02:02 -0400363 p := s.base() + uintptr(spf.special.offset)/s.elemsize*s.elemsize
Austin Clements608c1b02015-09-24 14:39:27 -0400364
365 // Mark everything that can be reached from
366 // the object (but *not* the object itself or
367 // we'll never collect it).
368 scanobject(p, gcw)
369
370 // The special itself is a root.
Michael Matloob432cb662015-11-11 12:39:30 -0500371 scanblock(uintptr(unsafe.Pointer(&spf.fn)), sys.PtrSize, &oneptrmask[0], gcw)
Austin Clements572f08a2015-08-04 10:45:29 -0400372 }
Austin Clements608c1b02015-09-24 14:39:27 -0400373
374 unlock(&s.speciallock)
Austin Clements572f08a2015-08-04 10:45:29 -0400375 }
376}
377
Austin Clements65aa2da2015-10-04 20:56:11 -0700378// gcAssistAlloc performs GC work to make gp's assist debt positive.
379// gp must be the calling user gorountine.
Austin Clements4b2fde92015-03-16 14:22:00 -0400380//
Austin Clements65aa2da2015-10-04 20:56:11 -0700381// This must be called with preemption enabled.
Russ Cox484f8012015-02-19 13:38:46 -0500382//go:nowritebarrier
Austin Clements65aa2da2015-10-04 20:56:11 -0700383func gcAssistAlloc(gp *g) {
Austin Clements4f188c22015-07-22 15:14:54 -0400384 // Don't assist in non-preemptible contexts. These are
385 // generally fragile and won't allow the assist to block.
386 if getg() == gp.m.g0 {
387 return
388 }
389 if mp := getg().m; mp.locks > 0 || mp.preemptoff != "" {
390 return
391 }
392
Austin Clements89c341c2015-10-04 20:16:57 -0700393 // Compute the amount of scan work we need to do to make the
Austin Clements65aa2da2015-10-04 20:56:11 -0700394 // balance positive. We over-assist to build up credit for
395 // future allocations and amortize the cost of assisting.
396 debtBytes := -gp.gcAssistBytes + gcOverAssistBytes
Austin Clements89c341c2015-10-04 20:16:57 -0700397 scanWork := int64(gcController.assistWorkPerByte * float64(debtBytes))
Austin Clements4b2fde92015-03-16 14:22:00 -0400398
Austin Clements8f34b252015-07-22 16:55:04 -0400399retry:
Austin Clements4b2fde92015-03-16 14:22:00 -0400400 // Steal as much credit as we can from the background GC's
401 // scan credit. This is racy and may drop the background
402 // credit below 0 if two mutators steal at the same time. This
403 // will just cause steals to fail until credit is accumulated
404 // again, so in the long run it doesn't really matter, but we
405 // do have to handle the negative credit case.
Michael Matloob67faca72015-11-02 14:09:24 -0500406 bgScanCredit := atomic.Loadint64(&gcController.bgScanCredit)
Austin Clements4b2fde92015-03-16 14:22:00 -0400407 stolen := int64(0)
408 if bgScanCredit > 0 {
409 if bgScanCredit < scanWork {
410 stolen = bgScanCredit
Austin Clements89c341c2015-10-04 20:16:57 -0700411 gp.gcAssistBytes += 1 + int64(gcController.assistBytesPerWork*float64(stolen))
Austin Clements4b2fde92015-03-16 14:22:00 -0400412 } else {
413 stolen = scanWork
Austin Clements89c341c2015-10-04 20:16:57 -0700414 gp.gcAssistBytes += debtBytes
Austin Clements4b2fde92015-03-16 14:22:00 -0400415 }
Michael Matloob67faca72015-11-02 14:09:24 -0500416 atomic.Xaddint64(&gcController.bgScanCredit, -stolen)
Austin Clements4b2fde92015-03-16 14:22:00 -0400417
418 scanWork -= stolen
Austin Clements4b2fde92015-03-16 14:22:00 -0400419
420 if scanWork == 0 {
Austin Clements89c341c2015-10-04 20:16:57 -0700421 // We were able to steal all of the credit we
422 // needed.
Austin Clements4b2fde92015-03-16 14:22:00 -0400423 return
424 }
425 }
426
427 // Perform assist work
Austin Clements500c88d2015-07-23 17:55:01 -0400428 completed := false
Austin Clements4b2fde92015-03-16 14:22:00 -0400429 systemstack(func() {
Michael Matloob67faca72015-11-02 14:09:24 -0500430 if atomic.Load(&gcBlackenEnabled) == 0 {
Rick Hudson90a19962015-06-01 18:16:03 -0400431 // The gcBlackenEnabled check in malloc races with the
432 // store that clears it but an atomic check in every malloc
433 // would be a performance hit.
434 // Instead we recheck it here on the non-preemptable system
435 // stack to determine if we should preform an assist.
Austin Clements8f34b252015-07-22 16:55:04 -0400436
437 // GC is done, so ignore any remaining debt.
Austin Clements15aa6bb2015-10-14 21:31:33 -0400438 gp.gcAssistBytes = 0
Rick Hudson90a19962015-06-01 18:16:03 -0400439 return
440 }
Austin Clements100da602015-03-17 12:17:47 -0400441 // Track time spent in this assist. Since we're on the
442 // system stack, this is non-preemptible, so we can
443 // just measure start and end time.
444 startTime := nanotime()
445
Michael Matloob67faca72015-11-02 14:09:24 -0500446 decnwait := atomic.Xadd(&work.nwait, -1)
Rick Hudson90a19962015-06-01 18:16:03 -0400447 if decnwait == work.nproc {
448 println("runtime: work.nwait =", decnwait, "work.nproc=", work.nproc)
449 throw("nwait > work.nprocs")
450 }
Austin Clements8d03acc2015-03-23 21:07:33 -0400451
Austin Clements1b4025f2015-04-19 15:22:20 -0400452 // drain own cached work first in the hopes that it
Austin Clements4b2fde92015-03-16 14:22:00 -0400453 // will be more cache friendly.
Austin Clements1b4025f2015-04-19 15:22:20 -0400454 gcw := &getg().m.p.ptr().gcw
Austin Clements8e8219d2015-10-04 23:00:01 -0400455 workDone := gcDrainN(gcw, scanWork)
Rick Hudson90a19962015-06-01 18:16:03 -0400456 // If we are near the end of the mark phase
457 // dispose of the gcw.
458 if gcBlackenPromptly {
459 gcw.dispose()
460 }
Austin Clements89c341c2015-10-04 20:16:57 -0700461
462 // Record that we did this much scan work.
Austin Clements15aa6bb2015-10-14 21:31:33 -0400463 //
Austin Clements89c341c2015-10-04 20:16:57 -0700464 // Back out the number of bytes of assist credit that
465 // this scan work counts for. The "1+" is a poor man's
466 // round-up, to ensure this adds credit even if
467 // assistBytesPerWork is very low.
468 gp.gcAssistBytes += 1 + int64(gcController.assistBytesPerWork*float64(workDone))
469
Austin Clements8d03acc2015-03-23 21:07:33 -0400470 // If this is the last worker and we ran out of work,
471 // signal a completion point.
Michael Matloob67faca72015-11-02 14:09:24 -0500472 incnwait := atomic.Xadd(&work.nwait, +1)
Rick Hudson90a19962015-06-01 18:16:03 -0400473 if incnwait > work.nproc {
474 println("runtime: work.nwait=", incnwait,
475 "work.nproc=", work.nproc,
476 "gcBlackenPromptly=", gcBlackenPromptly)
477 throw("work.nwait > work.nproc")
Austin Clements8d03acc2015-03-23 21:07:33 -0400478 }
479
Austin Clements4cca1cc2015-10-19 13:35:25 -0400480 if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
Rick Hudson90a19962015-06-01 18:16:03 -0400481 // This has reached a background completion
482 // point.
Austin Clements500c88d2015-07-23 17:55:01 -0400483 completed = true
Rick Hudson90a19962015-06-01 18:16:03 -0400484 }
Austin Clements100da602015-03-17 12:17:47 -0400485 duration := nanotime() - startTime
486 _p_ := gp.m.p.ptr()
487 _p_.gcAssistTime += duration
488 if _p_.gcAssistTime > gcAssistTimeSlack {
Michael Matloob67faca72015-11-02 14:09:24 -0500489 atomic.Xaddint64(&gcController.assistTime, _p_.gcAssistTime)
Austin Clements100da602015-03-17 12:17:47 -0400490 _p_.gcAssistTime = 0
491 }
Austin Clements4b2fde92015-03-16 14:22:00 -0400492 })
Austin Clements500c88d2015-07-23 17:55:01 -0400493
494 if completed {
Austin Clementsc99d7f72015-10-26 11:27:37 -0400495 gcMarkDone()
Austin Clements8f34b252015-07-22 16:55:04 -0400496 }
497
Austin Clements15aa6bb2015-10-14 21:31:33 -0400498 if gp.gcAssistBytes < 0 {
Austin Clements8f34b252015-07-22 16:55:04 -0400499 // We were unable steal enough credit or perform
500 // enough work to pay off the assist debt. We need to
501 // do one of these before letting the mutator allocate
Austin Clements15aa6bb2015-10-14 21:31:33 -0400502 // more to prevent over-allocation.
503 //
Austin Clements45652832015-10-15 17:58:17 -0400504 // If this is because we were preempted, reschedule
505 // and try some more.
506 if gp.preempt {
507 Gosched()
508 goto retry
509 }
510
Austin Clements15aa6bb2015-10-14 21:31:33 -0400511 // Add this G to an assist queue and park. When the GC
512 // has more background credit, it will satisfy queued
513 // assists before flushing to the global credit pool.
514 //
515 // Note that this does *not* get woken up when more
516 // work is added to the work list. The theory is that
517 // there wasn't enough work to do anyway, so we might
518 // as well let background marking take care of the
519 // work that is available.
520 lock(&work.assistQueue.lock)
Austin Clements65aa2da2015-10-04 20:56:11 -0700521
Austin Clements15aa6bb2015-10-14 21:31:33 -0400522 // If the GC cycle is over, just return. This is the
Austin Clementsc99d7f72015-10-26 11:27:37 -0400523 // likely path if we completed above. We do this
Austin Clements15aa6bb2015-10-14 21:31:33 -0400524 // under the lock to prevent a GC cycle from ending
525 // between this check and queuing the assist.
Michael Matloob67faca72015-11-02 14:09:24 -0500526 if atomic.Load(&gcBlackenEnabled) == 0 {
Austin Clements15aa6bb2015-10-14 21:31:33 -0400527 unlock(&work.assistQueue.lock)
528 return
529 }
530
531 oldHead, oldTail := work.assistQueue.head, work.assistQueue.tail
532 if oldHead == 0 {
533 work.assistQueue.head.set(gp)
534 } else {
535 oldTail.ptr().schedlink.set(gp)
536 }
537 work.assistQueue.tail.set(gp)
538 gp.schedlink.set(nil)
539 // Recheck for background credit now that this G is in
540 // the queue, but can still back out. This avoids a
541 // race in case background marking has flushed more
542 // credit since we checked above.
Michael Matloob67faca72015-11-02 14:09:24 -0500543 if atomic.Loadint64(&gcController.bgScanCredit) > 0 {
Austin Clements15aa6bb2015-10-14 21:31:33 -0400544 work.assistQueue.head = oldHead
545 work.assistQueue.tail = oldTail
546 if oldTail != 0 {
547 oldTail.ptr().schedlink.set(nil)
548 }
549 unlock(&work.assistQueue.lock)
550 goto retry
551 }
552 // Park for real.
Austin Clementsf84420c2015-10-29 22:40:36 -0400553 goparkunlock(&work.assistQueue.lock, "GC assist wait", traceEvGoBlock, 2)
Austin Clements15aa6bb2015-10-14 21:31:33 -0400554
555 // At this point either background GC has satisfied
556 // this G's assist debt, or the GC cycle is over.
Austin Clements500c88d2015-07-23 17:55:01 -0400557 }
Russ Cox484f8012015-02-19 13:38:46 -0500558}
559
Austin Clements15aa6bb2015-10-14 21:31:33 -0400560// gcWakeAllAssists wakes all currently blocked assists. This is used
Austin Clementsb05f18e2016-01-15 13:28:41 -0500561// at the end of a GC cycle. gcBlackenEnabled must be false to prevent
562// new assists from going to sleep after this point.
Austin Clements15aa6bb2015-10-14 21:31:33 -0400563func gcWakeAllAssists() {
564 lock(&work.assistQueue.lock)
565 injectglist(work.assistQueue.head.ptr())
566 work.assistQueue.head.set(nil)
567 work.assistQueue.tail.set(nil)
568 unlock(&work.assistQueue.lock)
569}
570
571// gcFlushBgCredit flushes scanWork units of background scan work
572// credit. This first satisfies blocked assists on the
573// work.assistQueue and then flushes any remaining credit to
574// gcController.bgScanCredit.
Austin Clementsab9d5f32015-11-19 11:25:55 -0500575//
576// Write barriers are disallowed because this is used by gcDrain after
577// it has ensured that all work is drained and this must preserve that
578// condition.
579//
580//go:nowritebarrierrec
Austin Clements15aa6bb2015-10-14 21:31:33 -0400581func gcFlushBgCredit(scanWork int64) {
582 if work.assistQueue.head == 0 {
583 // Fast path; there are no blocked assists. There's a
584 // small window here where an assist may add itself to
585 // the blocked queue and park. If that happens, we'll
586 // just get it on the next flush.
Michael Matloob67faca72015-11-02 14:09:24 -0500587 atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
Austin Clements15aa6bb2015-10-14 21:31:33 -0400588 return
589 }
590
591 scanBytes := int64(float64(scanWork) * gcController.assistBytesPerWork)
592
593 lock(&work.assistQueue.lock)
594 gp := work.assistQueue.head.ptr()
595 for gp != nil && scanBytes > 0 {
596 // Note that gp.gcAssistBytes is negative because gp
597 // is in debt. Think carefully about the signs below.
598 if scanBytes+gp.gcAssistBytes >= 0 {
599 // Satisfy this entire assist debt.
600 scanBytes += gp.gcAssistBytes
601 gp.gcAssistBytes = 0
602 xgp := gp
603 gp = gp.schedlink.ptr()
Austin Clements44497eb2016-05-17 18:46:03 -0400604 // It's important that we *not* put xgp in
605 // runnext. Otherwise, it's possible for user
606 // code to exploit the GC worker's high
607 // scheduler priority to get itself always run
608 // before other goroutines and always in the
609 // fresh quantum started by GC.
610 ready(xgp, 0, false)
Austin Clements15aa6bb2015-10-14 21:31:33 -0400611 } else {
612 // Partially satisfy this assist.
613 gp.gcAssistBytes += scanBytes
614 scanBytes = 0
615 // As a heuristic, we move this assist to the
616 // back of the queue so that large assists
617 // can't clog up the assist queue and
618 // substantially delay small assists.
619 xgp := gp
620 gp = gp.schedlink.ptr()
621 if gp == nil {
622 // gp is the only assist in the queue.
623 gp = xgp
624 } else {
625 xgp.schedlink = 0
626 work.assistQueue.tail.ptr().schedlink.set(xgp)
627 work.assistQueue.tail.set(xgp)
628 }
629 break
630 }
631 }
632 work.assistQueue.head.set(gp)
633 if gp == nil {
634 work.assistQueue.tail.set(nil)
635 }
636
637 if scanBytes > 0 {
638 // Convert from scan bytes back to work.
639 scanWork = int64(float64(scanBytes) * gcController.assistWorkPerByte)
Michael Matloob67faca72015-11-02 14:09:24 -0500640 atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
Austin Clements15aa6bb2015-10-14 21:31:33 -0400641 }
642 unlock(&work.assistQueue.lock)
643}
644
Austin Clementsa1f7db82016-05-23 22:05:51 -0400645// scanstack scans gp's stack, greying all pointers found on the stack.
646//
647// During mark phase, it also installs stack barriers while traversing
648// gp's stack. During mark termination, it stops scanning when it
649// reaches an unhit stack barrier.
650//
651// scanstack is marked go:systemstack because it must not be preempted
652// while using a workbuf.
653//
Russ Cox484f8012015-02-19 13:38:46 -0500654//go:nowritebarrier
Austin Clementsa1f7db82016-05-23 22:05:51 -0400655//go:systemstack
Austin Clements3be48b42016-05-23 22:14:53 -0400656func scanstack(gp *g, gcw *gcWork) {
Russ Cox484f8012015-02-19 13:38:46 -0500657 if gp.gcscanvalid {
658 return
659 }
660
661 if readgstatus(gp)&_Gscan == 0 {
662 print("runtime:scanstack: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", hex(readgstatus(gp)), "\n")
663 throw("scanstack - bad status")
664 }
665
666 switch readgstatus(gp) &^ _Gscan {
667 default:
668 print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
669 throw("mark - bad status")
670 case _Gdead:
671 return
672 case _Grunning:
673 print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
674 throw("scanstack: goroutine not stopped")
675 case _Grunnable, _Gsyscall, _Gwaiting:
676 // ok
677 }
678
679 if gp == getg() {
680 throw("can't scan our own stack")
681 }
682 mp := gp.m
683 if mp != nil && mp.helpgc != 0 {
684 throw("can't scan gchelper stack")
685 }
686
Austin Clementsf11e4eb2016-02-15 18:30:48 -0500687 // Shrink the stack if not much of it is being used. During
688 // concurrent GC, we can do this during concurrent mark.
689 if !work.markrootDone {
690 shrinkstack(gp)
691 }
692
693 // Prepare for stack barrier insertion/removal.
Austin Clements75293142015-06-05 11:07:21 -0400694 var sp, barrierOffset, nextBarrier uintptr
695 if gp.syscallsp != 0 {
696 sp = gp.syscallsp
697 } else {
698 sp = gp.sched.sp
699 }
Austin Clements269c9692016-03-02 14:52:08 -0500700 gcLockStackBarriers(gp) // Not necessary during mark term, but harmless.
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400701 switch gcphase {
Austin Clements82d14d72015-10-19 13:46:32 -0400702 case _GCmark:
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400703 // Install stack barriers during stack scan.
Austin Clements3bfc9df2015-08-26 13:54:26 -0400704 barrierOffset = uintptr(firstStackBarrierOffset)
Austin Clements75293142015-06-05 11:07:21 -0400705 nextBarrier = sp + barrierOffset
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400706
Russ Coxd5b40b62015-06-05 11:51:49 -0400707 if debug.gcstackbarrieroff > 0 {
708 nextBarrier = ^uintptr(0)
709 }
710
Austin Clements269c9692016-03-02 14:52:08 -0500711 // Remove any existing stack barriers before we
712 // install new ones.
713 gcRemoveStackBarriers(gp)
Austin Clements9c9d74a2015-11-18 14:10:40 -0500714
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400715 case _GCmarktermination:
Austin Clements269c9692016-03-02 14:52:08 -0500716 if !work.markrootDone {
717 // This is a STW GC. There may be stale stack
718 // barriers from an earlier cycle since we
719 // never passed through mark phase.
720 gcRemoveStackBarriers(gp)
721 }
722
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400723 if int(gp.stkbarPos) == len(gp.stkbar) {
724 // gp hit all of the stack barriers (or there
725 // were none). Re-scan the whole stack.
726 nextBarrier = ^uintptr(0)
727 } else {
728 // Only re-scan up to the lowest un-hit
729 // barrier. Any frames above this have not
Austin Clements82d14d72015-10-19 13:46:32 -0400730 // executed since the concurrent scan of gp and
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400731 // any writes through up-pointers to above
732 // this barrier had write barriers.
733 nextBarrier = gp.stkbar[gp.stkbarPos].savedLRPtr
734 if debugStackBarrier {
Austin Clements75293142015-06-05 11:07:21 -0400735 print("rescan below ", hex(nextBarrier), " in [", hex(sp), ",", hex(gp.stack.hi), ") goid=", gp.goid, "\n")
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400736 }
737 }
738
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400739 default:
740 throw("scanstack in wrong phase")
741 }
742
Austin Clementsf11e4eb2016-02-15 18:30:48 -0500743 // Scan the stack.
Austin Clementsbeedb1e2015-08-12 23:43:43 -0400744 var cache pcvalueCache
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400745 n := 0
Russ Cox484f8012015-02-19 13:38:46 -0500746 scanframe := func(frame *stkframe, unused unsafe.Pointer) bool {
Austin Clementsbeedb1e2015-08-12 23:43:43 -0400747 scanframeworker(frame, &cache, gcw)
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400748
749 if frame.fp > nextBarrier {
750 // We skip installing a barrier on bottom-most
751 // frame because on LR machines this LR is not
752 // on the stack.
Austin Clements82d14d72015-10-19 13:46:32 -0400753 if gcphase == _GCmark && n != 0 {
Austin Clementse2bb03f2015-08-26 12:16:51 -0400754 if gcInstallStackBarrier(gp, frame) {
755 barrierOffset *= 2
756 nextBarrier = sp + barrierOffset
757 }
Austin Clementsfaa7a7e2015-05-20 16:30:49 -0400758 } else if gcphase == _GCmarktermination {
759 // We just scanned a frame containing
760 // a return to a stack barrier. Since
761 // this frame never returned, we can
762 // stop scanning.
763 return false
764 }
765 }
766 n++
767
Russ Cox484f8012015-02-19 13:38:46 -0500768 return true
769 }
770 gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, scanframe, nil, 0)
771 tracebackdefers(gp, scanframe, nil)
Austin Clements269c9692016-03-02 14:52:08 -0500772 gcUnlockStackBarriers(gp)
Austin Clements9c9d74a2015-11-18 14:10:40 -0500773 if gcphase == _GCmark {
Austin Clements2a889b92016-03-04 11:58:26 -0500774 // gp may have added itself to the rescan list between
775 // when GC started and now. It's clean now, so remove
776 // it. This isn't safe during mark termination because
777 // mark termination is consuming this list, but it's
778 // also not necessary.
779 dequeueRescan(gp)
Austin Clements9c9d74a2015-11-18 14:10:40 -0500780 }
Russ Cox484f8012015-02-19 13:38:46 -0500781 gp.gcscanvalid = true
782}
783
784// Scan a stack frame: local variables and function arguments/results.
785//go:nowritebarrier
Austin Clementsbeedb1e2015-08-12 23:43:43 -0400786func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
Russ Cox484f8012015-02-19 13:38:46 -0500787
788 f := frame.fn
789 targetpc := frame.continpc
790 if targetpc == 0 {
791 // Frame is dead.
792 return
793 }
794 if _DebugGC > 1 {
795 print("scanframe ", funcname(f), "\n")
796 }
797 if targetpc != f.entry {
798 targetpc--
799 }
Austin Clementsbeedb1e2015-08-12 23:43:43 -0400800 pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
Russ Cox484f8012015-02-19 13:38:46 -0500801 if pcdata == -1 {
802 // We do not have a valid pcdata value but there might be a
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +0000803 // stackmap for this function. It is likely that we are looking
Russ Cox484f8012015-02-19 13:38:46 -0500804 // at the function prologue, assume so and hope for the best.
805 pcdata = 0
806 }
807
808 // Scan local variables if stack frame has been allocated.
809 size := frame.varp - frame.sp
810 var minsize uintptr
Jeremy Jackinsba09d062016-04-07 15:42:35 +0900811 switch sys.ArchFamily {
812 case sys.ARM64:
Michael Matloob432cb662015-11-11 12:39:30 -0500813 minsize = sys.SpAlign
Aram Hăvărneanu846ee042015-03-08 14:20:20 +0100814 default:
Michael Matloob432cb662015-11-11 12:39:30 -0500815 minsize = sys.MinFrameSize
Russ Cox484f8012015-02-19 13:38:46 -0500816 }
817 if size > minsize {
818 stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
819 if stkmap == nil || stkmap.n <= 0 {
820 print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
821 throw("missing stackmap")
822 }
823
824 // Locals bitmap information, scan just the pointers in locals.
825 if pcdata < 0 || pcdata >= stkmap.n {
826 // don't know where we are
827 print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
828 throw("scanframe: bad symbol table")
829 }
830 bv := stackmapdata(stkmap, pcdata)
Michael Matloob432cb662015-11-11 12:39:30 -0500831 size = uintptr(bv.n) * sys.PtrSize
Russ Cox484f8012015-02-19 13:38:46 -0500832 scanblock(frame.varp-size, size, bv.bytedata, gcw)
833 }
834
835 // Scan arguments.
836 if frame.arglen > 0 {
837 var bv bitvector
838 if frame.argmap != nil {
839 bv = *frame.argmap
840 } else {
841 stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
842 if stkmap == nil || stkmap.n <= 0 {
843 print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n")
844 throw("missing stackmap")
845 }
846 if pcdata < 0 || pcdata >= stkmap.n {
847 // don't know where we are
848 print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
849 throw("scanframe: bad symbol table")
850 }
851 bv = stackmapdata(stkmap, pcdata)
852 }
Michael Matloob432cb662015-11-11 12:39:30 -0500853 scanblock(frame.argp, uintptr(bv.n)*sys.PtrSize, bv.bytedata, gcw)
Russ Cox484f8012015-02-19 13:38:46 -0500854 }
855}
856
Austin Clements2a889b92016-03-04 11:58:26 -0500857// queueRescan adds gp to the stack rescan list and clears
858// gp.gcscanvalid. The caller must own gp and ensure that gp isn't
859// already on the rescan list.
860func queueRescan(gp *g) {
861 if gcphase == _GCoff {
862 gp.gcscanvalid = false
863 return
864 }
865 if gp.gcRescan != -1 {
866 throw("g already on rescan list")
867 }
868
869 lock(&work.rescan.lock)
870 gp.gcscanvalid = false
871
872 // Recheck gcphase under the lock in case there was a phase change.
873 if gcphase == _GCoff {
874 unlock(&work.rescan.lock)
875 return
876 }
877 if len(work.rescan.list) == cap(work.rescan.list) {
878 throw("rescan list overflow")
879 }
880 n := len(work.rescan.list)
881 gp.gcRescan = int32(n)
882 work.rescan.list = work.rescan.list[:n+1]
883 work.rescan.list[n].set(gp)
884 unlock(&work.rescan.lock)
885}
886
887// dequeueRescan removes gp from the stack rescan list, if gp is on
888// the rescan list. The caller must own gp.
889func dequeueRescan(gp *g) {
890 if gp.gcRescan == -1 {
891 return
892 }
893 if gcphase == _GCoff {
894 gp.gcRescan = -1
895 return
896 }
897
898 lock(&work.rescan.lock)
899 if work.rescan.list[gp.gcRescan].ptr() != gp {
900 throw("bad dequeueRescan")
901 }
902 // Careful: gp may itself be the last G on the list.
903 last := work.rescan.list[len(work.rescan.list)-1]
904 work.rescan.list[gp.gcRescan] = last
905 last.ptr().gcRescan = gp.gcRescan
906 gp.gcRescan = -1
907 work.rescan.list = work.rescan.list[:len(work.rescan.list)-1]
908 unlock(&work.rescan.lock)
909}
910
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400911type gcDrainFlags int
Austin Clements8d03acc2015-03-23 21:07:33 -0400912
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400913const (
914 gcDrainUntilPreempt gcDrainFlags = 1 << iota
Austin Clements62ba5202015-10-26 16:29:25 -0400915 gcDrainNoBlock
Austin Clementsc18b1632015-10-04 22:47:27 -0400916 gcDrainFlushBgCredit
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400917
Austin Clements62ba5202015-10-26 16:29:25 -0400918 // gcDrainBlock means neither gcDrainUntilPreempt or
919 // gcDrainNoBlock. It is the default, but callers should use
920 // the constant for documentation purposes.
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400921 gcDrainBlock gcDrainFlags = 0
922)
923
Austin Clements82d14d72015-10-19 13:46:32 -0400924// gcDrain scans roots and objects in work buffers, blackening grey
925// objects until all roots and work buffers have been drained.
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400926//
Austin Clements62ba5202015-10-26 16:29:25 -0400927// If flags&gcDrainUntilPreempt != 0, gcDrain returns when g.preempt
928// is set. This implies gcDrainNoBlock.
929//
930// If flags&gcDrainNoBlock != 0, gcDrain returns as soon as it is
931// unable to get more work. Otherwise, it will block until all
932// blocking calls are blocked in gcDrain.
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400933//
Austin Clementsc18b1632015-10-04 22:47:27 -0400934// If flags&gcDrainFlushBgCredit != 0, gcDrain flushes scan work
Austin Clements8e8219d2015-10-04 23:00:01 -0400935// credit to gcController.bgScanCredit every gcCreditSlack units of
Austin Clementsc18b1632015-10-04 22:47:27 -0400936// scan work.
Austin Clements62ba5202015-10-26 16:29:25 -0400937//
Russ Cox484f8012015-02-19 13:38:46 -0500938//go:nowritebarrier
Austin Clementsc18b1632015-10-04 22:47:27 -0400939func gcDrain(gcw *gcWork, flags gcDrainFlags) {
Ian Lance Taylorbe1ef462015-11-13 17:45:22 -0800940 if !writeBarrier.needed {
Austin Clementsf5e67e52015-07-24 12:33:23 -0400941 throw("gcDrain phase incorrect")
Russ Cox484f8012015-02-19 13:38:46 -0500942 }
943
Austin Clements82d14d72015-10-19 13:46:32 -0400944 gp := getg()
Rick Hudson9439fa12016-01-06 17:07:58 -0500945 preemptible := flags&gcDrainUntilPreempt != 0
Austin Clements62ba5202015-10-26 16:29:25 -0400946 blocking := flags&(gcDrainUntilPreempt|gcDrainNoBlock) == 0
Austin Clementsc18b1632015-10-04 22:47:27 -0400947 flushBgCredit := flags&gcDrainFlushBgCredit != 0
Austin Clements8d03acc2015-03-23 21:07:33 -0400948
Austin Clements82d14d72015-10-19 13:46:32 -0400949 // Drain root marking jobs.
950 if work.markrootNext < work.markrootJobs {
951 for blocking || !gp.preempt {
Michael Matloob67faca72015-11-02 14:09:24 -0500952 job := atomic.Xadd(&work.markrootNext, +1) - 1
Austin Clements82d14d72015-10-19 13:46:32 -0400953 if job >= work.markrootJobs {
954 break
955 }
Austin Clements7b229002015-11-23 18:44:03 -0500956 markroot(gcw, job)
Austin Clements82d14d72015-10-19 13:46:32 -0400957 }
958 }
959
Austin Clements8e8219d2015-10-04 23:00:01 -0400960 initScanWork := gcw.scanWork
Austin Clements8d03acc2015-03-23 21:07:33 -0400961
Austin Clements82d14d72015-10-19 13:46:32 -0400962 // Drain heap marking jobs.
Rick Hudson9439fa12016-01-06 17:07:58 -0500963 for !(preemptible && gp.preempt) {
964 // Try to keep work available on the global queue. We used to
965 // check if there were waiting workers, but it's better to
966 // just keep work available than to make workers wait. In the
967 // worst case, we'll do O(log(_WorkbufSize)) unnecessary
968 // balances.
969 if work.full == 0 {
Austin Clements8d03acc2015-03-23 21:07:33 -0400970 gcw.balance()
971 }
972
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400973 var b uintptr
974 if blocking {
975 b = gcw.get()
976 } else {
Rick Hudson1354b322016-03-14 12:17:48 -0400977 b = gcw.tryGetFast()
978 if b == 0 {
979 b = gcw.tryGet()
980 }
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400981 }
Austin Clements8d03acc2015-03-23 21:07:33 -0400982 if b == 0 {
Austin Clements9b3cdaf2015-10-04 22:42:43 -0400983 // work barrier reached or tryGet failed.
Austin Clements8d03acc2015-03-23 21:07:33 -0400984 break
985 }
Russ Cox4d0f3a12015-04-27 22:45:57 -0400986 scanobject(b, gcw)
Austin Clements8d03acc2015-03-23 21:07:33 -0400987
988 // Flush background scan work credit to the global
989 // account if we've accumulated enough locally so
990 // mutator assists can draw on it.
Austin Clements8e8219d2015-10-04 23:00:01 -0400991 if gcw.scanWork >= gcCreditSlack {
Michael Matloob67faca72015-11-02 14:09:24 -0500992 atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
Austin Clements8e8219d2015-10-04 23:00:01 -0400993 if flushBgCredit {
Austin Clements15aa6bb2015-10-14 21:31:33 -0400994 gcFlushBgCredit(gcw.scanWork - initScanWork)
Austin Clements8e8219d2015-10-04 23:00:01 -0400995 initScanWork = 0
996 }
997 gcw.scanWork = 0
Austin Clements8d03acc2015-03-23 21:07:33 -0400998 }
999 }
Austin Clements8e8219d2015-10-04 23:00:01 -04001000
Austin Clementsab9d5f32015-11-19 11:25:55 -05001001 // In blocking mode, write barriers are not allowed after this
1002 // point because we must preserve the condition that the work
1003 // buffers are empty.
1004
Austin Clements8e8219d2015-10-04 23:00:01 -04001005 // Flush remaining scan work credit.
1006 if gcw.scanWork > 0 {
Michael Matloob67faca72015-11-02 14:09:24 -05001007 atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
Austin Clements8e8219d2015-10-04 23:00:01 -04001008 if flushBgCredit {
Austin Clements15aa6bb2015-10-14 21:31:33 -04001009 gcFlushBgCredit(gcw.scanWork - initScanWork)
Austin Clements8e8219d2015-10-04 23:00:01 -04001010 }
1011 gcw.scanWork = 0
Austin Clements8d03acc2015-03-23 21:07:33 -04001012 }
1013}
1014
Austin Clements028f9722015-03-13 14:01:16 -04001015// gcDrainN blackens grey objects until it has performed roughly
Austin Clements45652832015-10-15 17:58:17 -04001016// scanWork units of scan work or the G is preempted. This is
1017// best-effort, so it may perform less work if it fails to get a work
1018// buffer. Otherwise, it will perform at least n units of work, but
1019// may perform more because scanning is always done in whole object
1020// increments. It returns the amount of scan work performed.
Russ Cox484f8012015-02-19 13:38:46 -05001021//go:nowritebarrier
Austin Clements8e8219d2015-10-04 23:00:01 -04001022func gcDrainN(gcw *gcWork, scanWork int64) int64 {
Ian Lance Taylorbe1ef462015-11-13 17:45:22 -08001023 if !writeBarrier.needed {
Austin Clementsf5e67e52015-07-24 12:33:23 -04001024 throw("gcDrainN phase incorrect")
1025 }
Austin Clements8e8219d2015-10-04 23:00:01 -04001026
1027 // There may already be scan work on the gcw, which we don't
1028 // want to claim was done by this call.
1029 workFlushed := -gcw.scanWork
1030
Austin Clements45652832015-10-15 17:58:17 -04001031 gp := getg().m.curg
1032 for !gp.preempt && workFlushed+gcw.scanWork < scanWork {
Rick Hudson9439fa12016-01-06 17:07:58 -05001033 // See gcDrain comment.
1034 if work.full == 0 {
1035 gcw.balance()
1036 }
1037
Russ Cox484f8012015-02-19 13:38:46 -05001038 // This might be a good place to add prefetch code...
1039 // if(wbuf.nobj > 4) {
1040 // PREFETCH(wbuf->obj[wbuf.nobj - 3];
1041 // }
Rick Hudson9439fa12016-01-06 17:07:58 -05001042 //
Rick Hudson1354b322016-03-14 12:17:48 -04001043 b := gcw.tryGetFast()
1044 if b == 0 {
1045 b = gcw.tryGet()
1046 }
1047
Russ Cox484f8012015-02-19 13:38:46 -05001048 if b == 0 {
Austin Clements8e8219d2015-10-04 23:00:01 -04001049 break
Russ Cox484f8012015-02-19 13:38:46 -05001050 }
Russ Cox4d0f3a12015-04-27 22:45:57 -04001051 scanobject(b, gcw)
Austin Clements8e8219d2015-10-04 23:00:01 -04001052
1053 // Flush background scan work credit.
1054 if gcw.scanWork >= gcCreditSlack {
Michael Matloob67faca72015-11-02 14:09:24 -05001055 atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
Austin Clements8e8219d2015-10-04 23:00:01 -04001056 workFlushed += gcw.scanWork
1057 gcw.scanWork = 0
1058 }
Russ Cox484f8012015-02-19 13:38:46 -05001059 }
Austin Clements8e8219d2015-10-04 23:00:01 -04001060
1061 // Unlike gcDrain, there's no need to flush remaining work
1062 // here because this never flushes to bgScanCredit and
1063 // gcw.dispose will flush any remaining work to scanWork.
1064
1065 return workFlushed + gcw.scanWork
Russ Cox484f8012015-02-19 13:38:46 -05001066}
1067
Russ Cox4d0f3a12015-04-27 22:45:57 -04001068// scanblock scans b as scanobject would, but using an explicit
1069// pointer bitmap instead of the heap bitmap.
Austin Clements3be3cbd2015-05-04 16:10:49 -04001070//
1071// This is used to scan non-heap roots, so it does not update
1072// gcw.bytesMarked or gcw.scanWork.
1073//
Russ Cox484f8012015-02-19 13:38:46 -05001074//go:nowritebarrier
Austin Clementscadd4f82015-03-12 13:09:30 -04001075func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
Russ Cox484f8012015-02-19 13:38:46 -05001076 // Use local copies of original parameters, so that a stack trace
1077 // due to one of the throws below shows the original block
1078 // base and extent.
1079 b := b0
1080 n := n0
1081
Russ Cox4d0f3a12015-04-27 22:45:57 -04001082 arena_start := mheap_.arena_start
1083 arena_used := mheap_.arena_used
Russ Cox484f8012015-02-19 13:38:46 -05001084
Russ Cox4d0f3a12015-04-27 22:45:57 -04001085 for i := uintptr(0); i < n; {
1086 // Find bits for the next word.
Michael Matloob432cb662015-11-11 12:39:30 -05001087 bits := uint32(*addb(ptrmask, i/(sys.PtrSize*8)))
Russ Cox4d0f3a12015-04-27 22:45:57 -04001088 if bits == 0 {
Michael Matloob432cb662015-11-11 12:39:30 -05001089 i += sys.PtrSize * 8
Russ Cox4d0f3a12015-04-27 22:45:57 -04001090 continue
1091 }
1092 for j := 0; j < 8 && i < n; j++ {
1093 if bits&1 != 0 {
1094 // Same work as in scanobject; see comments there.
1095 obj := *(*uintptr)(unsafe.Pointer(b + i))
Russ Cox4d0f3a12015-04-27 22:45:57 -04001096 if obj != 0 && arena_start <= obj && obj < arena_used {
Rick Hudson2063d5d2016-03-14 12:17:48 -04001097 if obj, hbits, span, objIndex := heapBitsForObject(obj, b, i); obj != 0 {
1098 greyobject(obj, b, i, hbits, span, gcw, objIndex)
Russ Cox4d0f3a12015-04-27 22:45:57 -04001099 }
1100 }
1101 }
1102 bits >>= 1
Michael Matloob432cb662015-11-11 12:39:30 -05001103 i += sys.PtrSize
Russ Cox484f8012015-02-19 13:38:46 -05001104 }
1105 }
1106}
1107
Russ Cox4d0f3a12015-04-27 22:45:57 -04001108// scanobject scans the object starting at b, adding pointers to gcw.
1109// b must point to the beginning of a heap object; scanobject consults
1110// the GC bitmap for the pointer mask and the spans for the size of the
Austin Clements30ded162016-05-11 16:29:07 -04001111// object.
Russ Cox484f8012015-02-19 13:38:46 -05001112//go:nowritebarrier
Russ Cox4d0f3a12015-04-27 22:45:57 -04001113func scanobject(b uintptr, gcw *gcWork) {
Austin Clements2a331ca2015-06-19 12:29:42 -04001114 // Note that arena_used may change concurrently during
1115 // scanobject and hence scanobject may encounter a pointer to
1116 // a newly allocated heap object that is *not* in
1117 // [start,used). It will not mark this object; however, we
1118 // know that it was just installed by a mutator, which means
1119 // that mutator will execute a write barrier and take care of
1120 // marking it. This is even more pronounced on relaxed memory
1121 // architectures since we access arena_used without barriers
1122 // or synchronization, but the same logic applies.
Russ Cox484f8012015-02-19 13:38:46 -05001123 arena_start := mheap_.arena_start
1124 arena_used := mheap_.arena_used
1125
1126 // Find bits of the beginning of the object.
Russ Cox4d0f3a12015-04-27 22:45:57 -04001127 // b must point to the beginning of a heap object, so
1128 // we can get its bits and span directly.
1129 hbits := heapBitsForAddr(b)
1130 s := spanOfUnchecked(b)
1131 n := s.elemsize
1132 if n == 0 {
1133 throw("scanobject n == 0")
Russ Cox484f8012015-02-19 13:38:46 -05001134 }
Russ Cox4d0f3a12015-04-27 22:45:57 -04001135
Austin Clements53c53982015-05-04 15:40:58 -04001136 var i uintptr
Michael Matloob432cb662015-11-11 12:39:30 -05001137 for i = 0; i < n; i += sys.PtrSize {
Russ Cox484f8012015-02-19 13:38:46 -05001138 // Find bits for this word.
Russ Cox4d0f3a12015-04-27 22:45:57 -04001139 if i != 0 {
1140 // Avoid needless hbits.next() on last iteration.
1141 hbits = hbits.next()
1142 }
Russ Cox0234dfd2015-05-04 10:19:24 -04001143 // During checkmarking, 1-word objects store the checkmark
1144 // in the type bit for the one word. The only one-word objects
1145 // are pointers, or else they'd be merged with other non-pointer
1146 // data into larger allocations.
Austin Clementsa20fd1f2016-04-29 14:51:48 -04001147 if i != 1*sys.PtrSize && !hbits.morePointers() {
Russ Coxfeb8a3b2015-05-04 11:30:10 -04001148 break // no more pointers in this object
Russ Cox484f8012015-02-19 13:38:46 -05001149 }
Austin Clementsd5e3d082016-04-29 15:19:11 -04001150 if !hbits.isPointer() {
Russ Coxfeb8a3b2015-05-04 11:30:10 -04001151 continue // not a pointer
1152 }
Russ Cox4d0f3a12015-04-27 22:45:57 -04001153
Russ Coxfeb8a3b2015-05-04 11:30:10 -04001154 // Work here is duplicated in scanblock and above.
1155 // If you make changes here, make changes there too.
Russ Cox484f8012015-02-19 13:38:46 -05001156 obj := *(*uintptr)(unsafe.Pointer(b + i))
1157
1158 // At this point we have extracted the next potential pointer.
Russ Cox8903b3d2015-05-18 11:40:29 -04001159 // Check if it points into heap and not back at the current object.
1160 if obj != 0 && arena_start <= obj && obj < arena_used && obj-b >= n {
Russ Cox4d0f3a12015-04-27 22:45:57 -04001161 // Mark the object.
Rick Hudson2063d5d2016-03-14 12:17:48 -04001162 if obj, hbits, span, objIndex := heapBitsForObject(obj, b, i); obj != 0 {
1163 greyobject(obj, b, i, hbits, span, gcw, objIndex)
Russ Cox4d0f3a12015-04-27 22:45:57 -04001164 }
Russ Cox484f8012015-02-19 13:38:46 -05001165 }
1166 }
Austin Clements50a66562015-03-12 16:53:57 -04001167 gcw.bytesMarked += uint64(n)
Austin Clements53c53982015-05-04 15:40:58 -04001168 gcw.scanWork += int64(i)
Russ Cox484f8012015-02-19 13:38:46 -05001169}
1170
1171// Shade the object if it isn't already.
1172// The object is not nil and known to be in the heap.
Austin Clements1b4025f2015-04-19 15:22:20 -04001173// Preemption must be disabled.
Russ Cox484f8012015-02-19 13:38:46 -05001174//go:nowritebarrier
1175func shade(b uintptr) {
Rick Hudson2063d5d2016-03-14 12:17:48 -04001176 if obj, hbits, span, objIndex := heapBitsForObject(b, 0, 0); obj != 0 {
Austin Clements1b4025f2015-04-19 15:22:20 -04001177 gcw := &getg().m.p.ptr().gcw
Rick Hudson2063d5d2016-03-14 12:17:48 -04001178 greyobject(obj, 0, 0, hbits, span, gcw, objIndex)
Rick Hudson90a19962015-06-01 18:16:03 -04001179 if gcphase == _GCmarktermination || gcBlackenPromptly {
Austin Clements1b4025f2015-04-19 15:22:20 -04001180 // Ps aren't allowed to cache work during mark
1181 // termination.
Russ Cox484f8012015-02-19 13:38:46 -05001182 gcw.dispose()
Russ Cox484f8012015-02-19 13:38:46 -05001183 }
1184 }
1185}
1186
1187// obj is the start of an object with mark mbits.
Austin Clements33e0f3d2015-04-27 15:42:45 -04001188// If it isn't already marked, mark it and enqueue into gcw.
Russ Cox484f8012015-02-19 13:38:46 -05001189// base and off are for debugging only and could be removed.
Austin Clements27df2e32015-11-24 14:03:58 -05001190//go:nowritebarrierrec
Rick Hudson2063d5d2016-03-14 12:17:48 -04001191func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork, objIndex uintptr) {
Russ Cox484f8012015-02-19 13:38:46 -05001192 // obj should be start of allocation, and so must be at least pointer-aligned.
Michael Matloob432cb662015-11-11 12:39:30 -05001193 if obj&(sys.PtrSize-1) != 0 {
Russ Cox484f8012015-02-19 13:38:46 -05001194 throw("greyobject: obj not pointer-aligned")
1195 }
Rick Hudson2063d5d2016-03-14 12:17:48 -04001196 mbits := span.markBitsForIndex(objIndex)
1197
Russ Cox89a091d2015-02-19 16:43:27 -05001198 if useCheckmark {
Rick Hudson3479b062016-02-11 13:57:58 -05001199 if !mbits.isMarked() {
Austin Clements506615d2015-03-12 14:26:04 -04001200 printlock()
Russ Cox484f8012015-02-19 13:38:46 -05001201 print("runtime:greyobject: checkmarks finds unexpected unmarked object obj=", hex(obj), "\n")
1202 print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")
1203
1204 // Dump the source (base) object
Austin Clements506615d2015-03-12 14:26:04 -04001205 gcDumpObject("base", base, off)
Russ Cox484f8012015-02-19 13:38:46 -05001206
1207 // Dump the object
Austin Clements506615d2015-03-12 14:26:04 -04001208 gcDumpObject("obj", obj, ^uintptr(0))
Russ Cox484f8012015-02-19 13:38:46 -05001209
Russ Cox484f8012015-02-19 13:38:46 -05001210 throw("checkmark found unmarked object")
1211 }
Russ Cox0234dfd2015-05-04 10:19:24 -04001212 if hbits.isCheckmarked(span.elemsize) {
Russ Cox484f8012015-02-19 13:38:46 -05001213 return
1214 }
Russ Cox0234dfd2015-05-04 10:19:24 -04001215 hbits.setCheckmarked(span.elemsize)
1216 if !hbits.isCheckmarked(span.elemsize) {
Russ Cox484f8012015-02-19 13:38:46 -05001217 throw("setCheckmarked and isCheckmarked disagree")
1218 }
1219 } else {
1220 // If marked we have nothing to do.
Rick Hudson3479b062016-02-11 13:57:58 -05001221 if mbits.isMarked() {
Russ Cox484f8012015-02-19 13:38:46 -05001222 return
1223 }
Rick Hudson2063d5d2016-03-14 12:17:48 -04001224 // mbits.setMarked() // Avoid extra call overhead with manual inlining.
1225 atomic.Or8(mbits.bytep, mbits.mask)
Austin Clementsda4874c2015-02-27 12:41:20 -05001226 // If this is a noscan object, fast-track it to black
1227 // instead of greying it.
Russ Cox0234dfd2015-05-04 10:19:24 -04001228 if !hbits.hasPointers(span.elemsize) {
Austin Clements50a66562015-03-12 16:53:57 -04001229 gcw.bytesMarked += uint64(span.elemsize)
Austin Clementsda4874c2015-02-27 12:41:20 -05001230 return
1231 }
Russ Cox484f8012015-02-19 13:38:46 -05001232 }
1233
1234 // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but
1235 // seems like a nice optimization that can be added back in.
1236 // There needs to be time between the PREFETCH and the use.
1237 // Previously we put the obj in an 8 element buffer that is drained at a rate
1238 // to give the PREFETCH time to do its work.
1239 // Use of PREFETCHNTA might be more appropriate than PREFETCH
Rick Hudson1354b322016-03-14 12:17:48 -04001240 if !gcw.putFast(obj) {
1241 gcw.put(obj)
1242 }
Russ Cox484f8012015-02-19 13:38:46 -05001243}
1244
Austin Clements506615d2015-03-12 14:26:04 -04001245// gcDumpObject dumps the contents of obj for debugging and marks the
1246// field at byte offset off in obj.
1247func gcDumpObject(label string, obj, off uintptr) {
Austin Clements3ca20212015-04-29 15:15:43 -04001248 if obj < mheap_.arena_start || obj >= mheap_.arena_used {
Austin Clementsb7c55ba2015-09-18 11:55:31 -04001249 print(label, "=", hex(obj), " is not in the Go heap\n")
Austin Clements3ca20212015-04-29 15:15:43 -04001250 return
1251 }
Austin Clements506615d2015-03-12 14:26:04 -04001252 k := obj >> _PageShift
1253 x := k
1254 x -= mheap_.arena_start >> _PageShift
1255 s := h_spans[x]
1256 print(label, "=", hex(obj), " k=", hex(k))
1257 if s == nil {
1258 print(" s=nil\n")
1259 return
1260 }
Austin Clementsb7adc412016-04-28 10:59:00 -04001261 print(" s.base()=", hex(s.base()), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n")
Austin Clements97b64d82015-09-18 12:06:24 -04001262 skipped := false
Michael Matloob432cb662015-11-11 12:39:30 -05001263 for i := uintptr(0); i < s.elemsize; i += sys.PtrSize {
Austin Clements97b64d82015-09-18 12:06:24 -04001264 // For big objects, just print the beginning (because
1265 // that usually hints at the object's type) and the
1266 // fields around off.
Michael Matloob432cb662015-11-11 12:39:30 -05001267 if !(i < 128*sys.PtrSize || off-16*sys.PtrSize < i && i < off+16*sys.PtrSize) {
Austin Clements97b64d82015-09-18 12:06:24 -04001268 skipped = true
1269 continue
1270 }
1271 if skipped {
1272 print(" ...\n")
1273 skipped = false
1274 }
Matthew Dempskya03bdc32016-02-29 15:01:00 -08001275 print(" *(", label, "+", i, ") = ", hex(*(*uintptr)(unsafe.Pointer(obj + i))))
Austin Clements506615d2015-03-12 14:26:04 -04001276 if i == off {
1277 print(" <==")
1278 }
1279 print("\n")
1280 }
Austin Clements97b64d82015-09-18 12:06:24 -04001281 if skipped {
1282 print(" ...\n")
1283 }
Austin Clements506615d2015-03-12 14:26:04 -04001284}
1285
Austin Clements64a26b72016-04-17 11:42:37 -04001286// gcmarknewobject marks a newly allocated object black. obj must
1287// not contain any non-nil pointers.
1288//
1289// This is nosplit so it can manipulate a gcWork without preemption.
1290//
Russ Cox484f8012015-02-19 13:38:46 -05001291//go:nowritebarrier
Austin Clements64a26b72016-04-17 11:42:37 -04001292//go:nosplit
1293func gcmarknewobject(obj, size, scanSize uintptr) {
Rick Hudson90a19962015-06-01 18:16:03 -04001294 if useCheckmark && !gcBlackenPromptly { // The world should be stopped so this should not happen.
Russ Cox484f8012015-02-19 13:38:46 -05001295 throw("gcmarknewobject called while doing checkmark")
1296 }
Rick Hudson3479b062016-02-11 13:57:58 -05001297 markBitsForAddr(obj).setMarked()
Austin Clements479501c2016-04-16 18:27:38 -04001298 gcw := &getg().m.p.ptr().gcw
Austin Clements64a26b72016-04-17 11:42:37 -04001299 gcw.bytesMarked += uint64(size)
Austin Clements479501c2016-04-16 18:27:38 -04001300 gcw.scanWork += int64(scanSize)
Russ Cox484f8012015-02-19 13:38:46 -05001301}
1302
1303// Checkmarking
1304
1305// To help debug the concurrent GC we remark with the world
1306// stopped ensuring that any object encountered has their normal
1307// mark bit set. To do this we use an orthogonal bit
1308// pattern to indicate the object is marked. The following pattern
Ainar Garipov7f9f70e2015-06-11 16:49:38 +03001309// uses the upper two bits in the object's boundary nibble.
Russ Cox484f8012015-02-19 13:38:46 -05001310// 01: scalar not marked
1311// 10: pointer not marked
1312// 11: pointer marked
1313// 00: scalar marked
1314// Xoring with 01 will flip the pattern from marked to unmarked and vica versa.
1315// The higher bit is 1 for pointers and 0 for scalars, whether the object
1316// is marked or not.
1317// The first nibble no longer holds the typeDead pattern indicating that the
1318// there are no more pointers in the object. This information is held
1319// in the second nibble.
1320
Russ Cox89a091d2015-02-19 16:43:27 -05001321// If useCheckmark is true, marking of an object uses the
1322// checkmark bits (encoding above) instead of the standard
1323// mark bits.
1324var useCheckmark = false
Russ Cox484f8012015-02-19 13:38:46 -05001325
1326//go:nowritebarrier
1327func initCheckmarks() {
Russ Cox89a091d2015-02-19 16:43:27 -05001328 useCheckmark = true
Russ Cox484f8012015-02-19 13:38:46 -05001329 for _, s := range work.spans {
1330 if s.state == _MSpanInUse {
1331 heapBitsForSpan(s.base()).initCheckmarkSpan(s.layout())
1332 }
1333 }
1334}
1335
1336func clearCheckmarks() {
Russ Cox89a091d2015-02-19 16:43:27 -05001337 useCheckmark = false
Russ Cox484f8012015-02-19 13:38:46 -05001338 for _, s := range work.spans {
1339 if s.state == _MSpanInUse {
1340 heapBitsForSpan(s.base()).clearCheckmarkSpan(s.layout())
1341 }
1342 }
1343}