github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/runtime/mgcmark.go (about) 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: marking and scanning 6 7 package runtime 8 9 import "unsafe" 10 11 // Scan all of the stacks, greying (or graying if in America) the referents 12 // but not blackening them since the mark write barrier isn't installed. 13 //go:nowritebarrier 14 func gcscan_m() { 15 _g_ := getg() 16 17 // Grab the g that called us and potentially allow rescheduling. 18 // This allows it to be scanned like other goroutines. 19 mastergp := _g_.m.curg 20 casgstatus(mastergp, _Grunning, _Gwaiting) 21 mastergp.waitreason = "garbage collection scan" 22 23 // Span sweeping has been done by finishsweep_m. 24 // Long term we will want to make this goroutine runnable 25 // by placing it onto a scanenqueue state and then calling 26 // runtimeĀ·restartg(mastergp) to make it Grunnable. 27 // At the bottom we will want to return this p back to the scheduler. 28 29 // Prepare flag indicating that the scan has not been completed. 30 local_allglen := gcResetGState() 31 32 work.nwait = 0 33 work.ndone = 0 34 work.nproc = 1 // For now do not do this in parallel. 35 // ackgcphase is not needed since we are not scanning running goroutines. 36 parforsetup(work.markfor, work.nproc, uint32(_RootCount+local_allglen), false, markroot) 37 parfordo(work.markfor) 38 39 lock(&allglock) 40 // Check that gc work is done. 41 for i := 0; i < local_allglen; i++ { 42 gp := allgs[i] 43 if !gp.gcworkdone { 44 throw("scan missed a g") 45 } 46 } 47 unlock(&allglock) 48 49 casgstatus(mastergp, _Gwaiting, _Grunning) 50 // Let the g that called us continue to run. 51 } 52 53 // ptrmask for an allocation containing a single pointer. 54 var oneptr = [...]uint8{typePointer} 55 56 //go:nowritebarrier 57 func markroot(desc *parfor, i uint32) { 58 var gcw gcWork 59 60 // Note: if you add a case here, please also update heapdump.go:dumproots. 61 switch i { 62 case _RootData: 63 for datap := &firstmoduledata; datap != nil; datap = datap.next { 64 scanblock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, &gcw) 65 } 66 67 case _RootBss: 68 for datap := &firstmoduledata; datap != nil; datap = datap.next { 69 scanblock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, &gcw) 70 } 71 72 case _RootFinalizers: 73 for fb := allfin; fb != nil; fb = fb.alllink { 74 scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), uintptr(fb.cnt)*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], &gcw) 75 } 76 77 case _RootSpans: 78 // mark MSpan.specials 79 sg := mheap_.sweepgen 80 for spanidx := uint32(0); spanidx < uint32(len(work.spans)); spanidx++ { 81 s := work.spans[spanidx] 82 if s.state != mSpanInUse { 83 continue 84 } 85 if !useCheckmark && s.sweepgen != sg { 86 // sweepgen was updated (+2) during non-checkmark GC pass 87 print("sweep ", s.sweepgen, " ", sg, "\n") 88 throw("gc: unswept span") 89 } 90 for sp := s.specials; sp != nil; sp = sp.next { 91 if sp.kind != _KindSpecialFinalizer { 92 continue 93 } 94 // don't mark finalized object, but scan it so we 95 // retain everything it points to. 96 spf := (*specialfinalizer)(unsafe.Pointer(sp)) 97 // A finalizer can be set for an inner byte of an object, find object beginning. 98 p := uintptr(s.start<<_PageShift) + uintptr(spf.special.offset)/s.elemsize*s.elemsize 99 if gcphase != _GCscan { 100 scanblock(p, s.elemsize, nil, &gcw) // scanned during mark phase 101 } 102 scanblock(uintptr(unsafe.Pointer(&spf.fn)), ptrSize, &oneptr[0], &gcw) 103 } 104 } 105 106 case _RootFlushCaches: 107 if gcphase != _GCscan { // Do not flush mcaches during GCscan phase. 108 flushallmcaches() 109 } 110 111 default: 112 // the rest is scanning goroutine stacks 113 if uintptr(i-_RootCount) >= allglen { 114 throw("markroot: bad index") 115 } 116 gp := allgs[i-_RootCount] 117 118 // remember when we've first observed the G blocked 119 // needed only to output in traceback 120 status := readgstatus(gp) // We are not in a scan state 121 if (status == _Gwaiting || status == _Gsyscall) && gp.waitsince == 0 { 122 gp.waitsince = work.tstart 123 } 124 125 // Shrink a stack if not much of it is being used but not in the scan phase. 126 if gcphase == _GCmarktermination { 127 // Shrink during STW GCmarktermination phase thus avoiding 128 // complications introduced by shrinking during 129 // non-STW phases. 130 shrinkstack(gp) 131 } 132 if readgstatus(gp) == _Gdead { 133 gp.gcworkdone = true 134 } else { 135 gp.gcworkdone = false 136 } 137 restart := stopg(gp) 138 139 // goroutine will scan its own stack when it stops running. 140 // Wait until it has. 141 for readgstatus(gp) == _Grunning && !gp.gcworkdone { 142 } 143 144 // scanstack(gp) is done as part of gcphasework 145 // But to make sure we finished we need to make sure that 146 // the stack traps have all responded so drop into 147 // this while loop until they respond. 148 for !gp.gcworkdone { 149 status = readgstatus(gp) 150 if status == _Gdead { 151 gp.gcworkdone = true // scan is a noop 152 break 153 } 154 if status == _Gwaiting || status == _Grunnable { 155 restart = stopg(gp) 156 } 157 } 158 if restart { 159 restartg(gp) 160 } 161 } 162 163 // Root aren't part of the heap, so don't count them toward 164 // marked heap bytes. 165 gcw.bytesMarked = 0 166 gcw.dispose() 167 } 168 169 // gchelpwork does a small bounded amount of gc work. The purpose is to 170 // shorten the time (as measured by allocations) spent doing a concurrent GC. 171 // The number of mutator calls is roughly propotional to the number of allocations 172 // made by that mutator. This slows down the allocation while speeding up the GC. 173 //go:nowritebarrier 174 func gchelpwork() { 175 switch gcphase { 176 default: 177 throw("gcphasework in bad gcphase") 178 case _GCoff, _GCquiesce, _GCstw: 179 // No work. 180 case _GCsweep: 181 // We could help by calling sweepone to sweep a single span. 182 // _ = sweepone() 183 case _GCscan: 184 // scan the stack, mark the objects, put pointers in work buffers 185 // hanging off the P where this is being run. 186 // scanstack(gp) 187 case _GCmark: 188 // drain your own currentwbuf first in the hopes that it will 189 // be more cache friendly. 190 var gcw gcWork 191 gcw.initFromCache() 192 const n = len(workbuf{}.obj) 193 gcDrainN(&gcw, n) // drain upto one buffer's worth of objects 194 gcw.dispose() 195 case _GCmarktermination: 196 // We should never be here since the world is stopped. 197 // All available mark work will be emptied before returning. 198 throw("gcphasework in bad gcphase") 199 } 200 } 201 202 // The gp has been moved to a GC safepoint. GC phase specific 203 // work is done here. 204 //go:nowritebarrier 205 func gcphasework(gp *g) { 206 switch gcphase { 207 default: 208 throw("gcphasework in bad gcphase") 209 case _GCoff, _GCquiesce, _GCstw, _GCsweep: 210 // No work. 211 case _GCscan: 212 // scan the stack, mark the objects, put pointers in work buffers 213 // hanging off the P where this is being run. 214 // Indicate that the scan is valid until the goroutine runs again 215 scanstack(gp) 216 case _GCmark: 217 // No work. 218 case _GCmarktermination: 219 scanstack(gp) 220 // All available mark work will be emptied before returning. 221 } 222 gp.gcworkdone = true 223 } 224 225 //go:nowritebarrier 226 func scanstack(gp *g) { 227 if gp.gcscanvalid { 228 return 229 } 230 231 if readgstatus(gp)&_Gscan == 0 { 232 print("runtime:scanstack: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", hex(readgstatus(gp)), "\n") 233 throw("scanstack - bad status") 234 } 235 236 switch readgstatus(gp) &^ _Gscan { 237 default: 238 print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n") 239 throw("mark - bad status") 240 case _Gdead: 241 return 242 case _Grunning: 243 print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n") 244 throw("scanstack: goroutine not stopped") 245 case _Grunnable, _Gsyscall, _Gwaiting: 246 // ok 247 } 248 249 if gp == getg() { 250 throw("can't scan our own stack") 251 } 252 mp := gp.m 253 if mp != nil && mp.helpgc != 0 { 254 throw("can't scan gchelper stack") 255 } 256 257 var gcw gcWork 258 gcw.initFromCache() 259 scanframe := func(frame *stkframe, unused unsafe.Pointer) bool { 260 // Pick up gcw as free variable so gentraceback and friends can 261 // keep the same signature. 262 scanframeworker(frame, unused, &gcw) 263 return true 264 } 265 gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, scanframe, nil, 0) 266 tracebackdefers(gp, scanframe, nil) 267 // Stacks aren't part of the heap, so don't count them toward 268 // marked heap bytes. 269 gcw.bytesMarked = 0 270 gcw.disposeToCache() 271 gp.gcscanvalid = true 272 } 273 274 // Scan a stack frame: local variables and function arguments/results. 275 //go:nowritebarrier 276 func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) { 277 278 f := frame.fn 279 targetpc := frame.continpc 280 if targetpc == 0 { 281 // Frame is dead. 282 return 283 } 284 if _DebugGC > 1 { 285 print("scanframe ", funcname(f), "\n") 286 } 287 if targetpc != f.entry { 288 targetpc-- 289 } 290 pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc) 291 if pcdata == -1 { 292 // We do not have a valid pcdata value but there might be a 293 // stackmap for this function. It is likely that we are looking 294 // at the function prologue, assume so and hope for the best. 295 pcdata = 0 296 } 297 298 // Scan local variables if stack frame has been allocated. 299 size := frame.varp - frame.sp 300 var minsize uintptr 301 switch thechar { 302 case '6', '8': 303 minsize = 0 304 case '7': 305 minsize = spAlign 306 default: 307 minsize = ptrSize 308 } 309 if size > minsize { 310 stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps)) 311 if stkmap == nil || stkmap.n <= 0 { 312 print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n") 313 throw("missing stackmap") 314 } 315 316 // Locals bitmap information, scan just the pointers in locals. 317 if pcdata < 0 || pcdata >= stkmap.n { 318 // don't know where we are 319 print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n") 320 throw("scanframe: bad symbol table") 321 } 322 bv := stackmapdata(stkmap, pcdata) 323 size = (uintptr(bv.n) / typeBitsWidth) * ptrSize 324 scanblock(frame.varp-size, size, bv.bytedata, gcw) 325 } 326 327 // Scan arguments. 328 if frame.arglen > 0 { 329 var bv bitvector 330 if frame.argmap != nil { 331 bv = *frame.argmap 332 } else { 333 stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps)) 334 if stkmap == nil || stkmap.n <= 0 { 335 print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n") 336 throw("missing stackmap") 337 } 338 if pcdata < 0 || pcdata >= stkmap.n { 339 // don't know where we are 340 print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n") 341 throw("scanframe: bad symbol table") 342 } 343 bv = stackmapdata(stkmap, pcdata) 344 } 345 scanblock(frame.argp, uintptr(bv.n)/typeBitsWidth*ptrSize, bv.bytedata, gcw) 346 } 347 } 348 349 // gcDrain scans objects in work buffers, blackening grey 350 // objects until all work buffers have been drained. 351 //go:nowritebarrier 352 func gcDrain(gcw *gcWork) { 353 if gcphase != _GCmark && gcphase != _GCmarktermination { 354 throw("scanblock phase incorrect") 355 } 356 357 for { 358 // If another proc wants a pointer, give it some. 359 if work.nwait > 0 && work.full == 0 { 360 gcw.balance() 361 } 362 363 b := gcw.get() 364 if b == 0 { 365 // work barrier reached 366 break 367 } 368 // If the current wbuf is filled by the scan a new wbuf might be 369 // returned that could possibly hold only a single object. This 370 // could result in each iteration draining only a single object 371 // out of the wbuf passed in + a single object placed 372 // into an empty wbuf in scanobject so there could be 373 // a performance hit as we keep fetching fresh wbufs. 374 scanobject(b, 0, nil, gcw) 375 } 376 checknocurrentwbuf() 377 } 378 379 // gcDrainN scans n objects, blackening grey objects. 380 //go:nowritebarrier 381 func gcDrainN(gcw *gcWork, n int) { 382 checknocurrentwbuf() 383 for i := 0; i < n; i++ { 384 // This might be a good place to add prefetch code... 385 // if(wbuf.nobj > 4) { 386 // PREFETCH(wbuf->obj[wbuf.nobj - 3]; 387 // } 388 b := gcw.tryGet() 389 if b == 0 { 390 return 391 } 392 scanobject(b, 0, nil, gcw) 393 } 394 } 395 396 // scanblock scans b as scanobject would. 397 // If the gcphase is GCscan, scanblock performs additional checks. 398 //go:nowritebarrier 399 func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) { 400 // Use local copies of original parameters, so that a stack trace 401 // due to one of the throws below shows the original block 402 // base and extent. 403 b := b0 404 n := n0 405 406 // ptrmask can have 2 possible values: 407 // 1. nil - obtain pointer mask from GC bitmap. 408 // 2. pointer to a compact mask (for stacks and data). 409 410 scanobject(b, n, ptrmask, gcw) 411 if gcphase == _GCscan { 412 if inheap(b) && ptrmask == nil { 413 // b is in heap, we are in GCscan so there should be a ptrmask. 414 throw("scanblock: In GCscan phase and inheap is true.") 415 } 416 } 417 } 418 419 // Scan the object b of size n bytes, adding pointers to wbuf. 420 // If ptrmask != nil, it specifies where pointers are in b. 421 // If ptrmask == nil, the GC bitmap should be consulted. 422 // In this case, n may be an overestimate of the size; the GC bitmap 423 // must also be used to make sure the scan stops at the end of b. 424 //go:nowritebarrier 425 func scanobject(b, n uintptr, ptrmask *uint8, gcw *gcWork) { 426 arena_start := mheap_.arena_start 427 arena_used := mheap_.arena_used 428 429 // Find bits of the beginning of the object. 430 var hbits heapBits 431 432 if ptrmask == nil { 433 var s *mspan 434 b, hbits, s = heapBitsForObject(b) 435 if b == 0 { 436 return 437 } 438 n = s.elemsize 439 if n == 0 { 440 throw("scanobject n == 0") 441 } 442 } 443 for i := uintptr(0); i < n; i += ptrSize { 444 // Find bits for this word. 445 var bits uintptr 446 if ptrmask != nil { 447 // dense mask (stack or data) 448 bits = (uintptr(*(*byte)(add(unsafe.Pointer(ptrmask), (i/ptrSize)/4))) >> (((i / ptrSize) % 4) * typeBitsWidth)) & typeMask 449 } else { 450 bits = uintptr(hbits.typeBits()) 451 if bits == typeDead { 452 break // no more pointers in this object 453 } 454 hbits = hbits.next() 455 } 456 457 if bits <= typeScalar { // typeScalar, typeDead, typeScalarMarked 458 continue 459 } 460 461 if bits&typePointer != typePointer { 462 print("gc useCheckmark=", useCheckmark, " b=", hex(b), " ptrmask=", ptrmask, "\n") 463 throw("unexpected garbage collection bits") 464 } 465 466 obj := *(*uintptr)(unsafe.Pointer(b + i)) 467 468 // At this point we have extracted the next potential pointer. 469 // Check if it points into heap. 470 if obj == 0 || obj < arena_start || obj >= arena_used { 471 continue 472 } 473 474 if mheap_.shadow_enabled && debug.wbshadow >= 2 && debug.gccheckmark > 0 && useCheckmark { 475 checkwbshadow((*uintptr)(unsafe.Pointer(b + i))) 476 } 477 478 // Mark the object. 479 if obj, hbits, span := heapBitsForObject(obj); obj != 0 { 480 greyobject(obj, b, i, hbits, span, gcw) 481 } 482 } 483 gcw.bytesMarked += uint64(n) 484 } 485 486 // Shade the object if it isn't already. 487 // The object is not nil and known to be in the heap. 488 //go:nowritebarrier 489 func shade(b uintptr) { 490 if !inheap(b) { 491 throw("shade: passed an address not in the heap") 492 } 493 if obj, hbits, span := heapBitsForObject(b); obj != 0 { 494 // TODO: this would be a great place to put a check to see 495 // if we are harvesting and if we are then we should 496 // figure out why there is a call to shade when the 497 // harvester thinks we are in a STW. 498 // if atomicload(&harvestingwbufs) == uint32(1) { 499 // // Throw here to discover write barriers 500 // // being executed during a STW. 501 // throw("shade during harvest") 502 // } 503 504 var gcw gcWork 505 greyobject(obj, 0, 0, hbits, span, &gcw) 506 // This is part of the write barrier so put the wbuf back. 507 if gcphase == _GCmarktermination { 508 gcw.dispose() 509 } else { 510 // If we added any pointers to the gcw, then 511 // currentwbuf must be nil because 1) 512 // greyobject got its wbuf from currentwbuf 513 // and 2) shade runs on the systemstack, so 514 // we're still on the same M. If either of 515 // these becomes no longer true, we need to 516 // rethink this. 517 gcw.disposeToCache() 518 } 519 } 520 } 521 522 // obj is the start of an object with mark mbits. 523 // If it isn't already marked, mark it and enqueue into workbuf. 524 // Return possibly new workbuf to use. 525 // base and off are for debugging only and could be removed. 526 //go:nowritebarrier 527 func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork) { 528 // obj should be start of allocation, and so must be at least pointer-aligned. 529 if obj&(ptrSize-1) != 0 { 530 throw("greyobject: obj not pointer-aligned") 531 } 532 533 if useCheckmark { 534 if !hbits.isMarked() { 535 printlock() 536 print("runtime:greyobject: checkmarks finds unexpected unmarked object obj=", hex(obj), "\n") 537 print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n") 538 539 // Dump the source (base) object 540 gcDumpObject("base", base, off) 541 542 // Dump the object 543 gcDumpObject("obj", obj, ^uintptr(0)) 544 545 throw("checkmark found unmarked object") 546 } 547 if !hbits.isCheckmarked() { 548 return 549 } 550 hbits.setCheckmarked() 551 if !hbits.isCheckmarked() { 552 throw("setCheckmarked and isCheckmarked disagree") 553 } 554 } else { 555 // If marked we have nothing to do. 556 if hbits.isMarked() { 557 return 558 } 559 560 hbits.setMarked() 561 562 // If this is a noscan object, fast-track it to black 563 // instead of greying it. 564 if hbits.typeBits() == typeDead { 565 gcw.bytesMarked += uint64(span.elemsize) 566 return 567 } 568 } 569 570 // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but 571 // seems like a nice optimization that can be added back in. 572 // There needs to be time between the PREFETCH and the use. 573 // Previously we put the obj in an 8 element buffer that is drained at a rate 574 // to give the PREFETCH time to do its work. 575 // Use of PREFETCHNTA might be more appropriate than PREFETCH 576 577 gcw.put(obj) 578 } 579 580 // gcDumpObject dumps the contents of obj for debugging and marks the 581 // field at byte offset off in obj. 582 func gcDumpObject(label string, obj, off uintptr) { 583 k := obj >> _PageShift 584 x := k 585 x -= mheap_.arena_start >> _PageShift 586 s := h_spans[x] 587 print(label, "=", hex(obj), " k=", hex(k)) 588 if s == nil { 589 print(" s=nil\n") 590 return 591 } 592 print(" s.start*_PageSize=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n") 593 for i := uintptr(0); i < s.elemsize; i += ptrSize { 594 print(" *(", label, "+", i, ") = ", hex(*(*uintptr)(unsafe.Pointer(obj + uintptr(i))))) 595 if i == off { 596 print(" <==") 597 } 598 print("\n") 599 } 600 } 601 602 // When in GCmarkterminate phase we allocate black. 603 //go:nowritebarrier 604 func gcmarknewobject_m(obj, size uintptr) { 605 if gcphase != _GCmarktermination { 606 throw("marking new object while not in mark termination phase") 607 } 608 if useCheckmark { // The world should be stopped so this should not happen. 609 throw("gcmarknewobject called while doing checkmark") 610 } 611 612 heapBitsForAddr(obj).setMarked() 613 xadd64(&work.bytesMarked, int64(size)) 614 } 615 616 // Checkmarking 617 618 // To help debug the concurrent GC we remark with the world 619 // stopped ensuring that any object encountered has their normal 620 // mark bit set. To do this we use an orthogonal bit 621 // pattern to indicate the object is marked. The following pattern 622 // uses the upper two bits in the object's bounday nibble. 623 // 01: scalar not marked 624 // 10: pointer not marked 625 // 11: pointer marked 626 // 00: scalar marked 627 // Xoring with 01 will flip the pattern from marked to unmarked and vica versa. 628 // The higher bit is 1 for pointers and 0 for scalars, whether the object 629 // is marked or not. 630 // The first nibble no longer holds the typeDead pattern indicating that the 631 // there are no more pointers in the object. This information is held 632 // in the second nibble. 633 634 // If useCheckmark is true, marking of an object uses the 635 // checkmark bits (encoding above) instead of the standard 636 // mark bits. 637 var useCheckmark = false 638 639 //go:nowritebarrier 640 func initCheckmarks() { 641 useCheckmark = true 642 for _, s := range work.spans { 643 if s.state == _MSpanInUse { 644 heapBitsForSpan(s.base()).initCheckmarkSpan(s.layout()) 645 } 646 } 647 } 648 649 func clearCheckmarks() { 650 useCheckmark = false 651 for _, s := range work.spans { 652 if s.state == _MSpanInUse { 653 heapBitsForSpan(s.base()).clearCheckmarkSpan(s.layout()) 654 } 655 } 656 }