github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/runtime/mheap.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 // Page heap. 6 // 7 // See malloc.go for overview. 8 9 package runtime 10 11 import ( 12 "runtime/internal/atomic" 13 "runtime/internal/sys" 14 "unsafe" 15 ) 16 17 // minPhysPageSize is a lower-bound on the physical page size. The 18 // true physical page size may be larger than this. In contrast, 19 // sys.PhysPageSize is an upper-bound on the physical page size. 20 const minPhysPageSize = 4096 21 22 // Main malloc heap. 23 // The heap itself is the "free[]" and "large" arrays, 24 // but all the other global data is here too. 25 // 26 // mheap must not be heap-allocated because it contains mSpanLists, 27 // which must not be heap-allocated. 28 // 29 //go:notinheap 30 type mheap struct { 31 lock mutex 32 free [_MaxMHeapList]mSpanList // free lists of given length up to _MaxMHeapList 33 freelarge mTreap // free treap of length >= _MaxMHeapList 34 busy [_MaxMHeapList]mSpanList // busy lists of large spans of given length 35 busylarge mSpanList // busy lists of large spans length >= _MaxMHeapList 36 sweepgen uint32 // sweep generation, see comment in mspan 37 sweepdone uint32 // all spans are swept 38 sweepers uint32 // number of active sweepone calls 39 40 // allspans is a slice of all mspans ever created. Each mspan 41 // appears exactly once. 42 // 43 // The memory for allspans is manually managed and can be 44 // reallocated and move as the heap grows. 45 // 46 // In general, allspans is protected by mheap_.lock, which 47 // prevents concurrent access as well as freeing the backing 48 // store. Accesses during STW might not hold the lock, but 49 // must ensure that allocation cannot happen around the 50 // access (since that may free the backing store). 51 allspans []*mspan // all spans out there 52 53 // spans is a lookup table to map virtual address page IDs to *mspan. 54 // For allocated spans, their pages map to the span itself. 55 // For free spans, only the lowest and highest pages map to the span itself. 56 // Internal pages map to an arbitrary span. 57 // For pages that have never been allocated, spans entries are nil. 58 // 59 // This is backed by a reserved region of the address space so 60 // it can grow without moving. The memory up to len(spans) is 61 // mapped. cap(spans) indicates the total reserved memory. 62 spans []*mspan 63 64 // sweepSpans contains two mspan stacks: one of swept in-use 65 // spans, and one of unswept in-use spans. These two trade 66 // roles on each GC cycle. Since the sweepgen increases by 2 67 // on each cycle, this means the swept spans are in 68 // sweepSpans[sweepgen/2%2] and the unswept spans are in 69 // sweepSpans[1-sweepgen/2%2]. Sweeping pops spans from the 70 // unswept stack and pushes spans that are still in-use on the 71 // swept stack. Likewise, allocating an in-use span pushes it 72 // on the swept stack. 73 sweepSpans [2]gcSweepBuf 74 75 _ uint32 // align uint64 fields on 32-bit for atomics 76 77 // Proportional sweep 78 pagesInUse uint64 // pages of spans in stats _MSpanInUse; R/W with mheap.lock 79 spanBytesAlloc uint64 // bytes of spans allocated this cycle; updated atomically 80 pagesSwept uint64 // pages swept this cycle; updated atomically 81 sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without 82 // TODO(austin): pagesInUse should be a uintptr, but the 386 83 // compiler can't 8-byte align fields. 84 85 // Malloc stats. 86 largealloc uint64 // bytes allocated for large objects 87 nlargealloc uint64 // number of large object allocations 88 largefree uint64 // bytes freed for large objects (>maxsmallsize) 89 nlargefree uint64 // number of frees for large objects (>maxsmallsize) 90 nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize) 91 92 // range of addresses we might see in the heap 93 bitmap uintptr // Points to one byte past the end of the bitmap 94 bitmap_mapped uintptr 95 arena_start uintptr 96 arena_used uintptr // One byte past usable heap arena. Set with setArenaUsed. 97 arena_end uintptr 98 arena_reserved bool 99 100 // central free lists for small size classes. 101 // the padding makes sure that the MCentrals are 102 // spaced CacheLineSize bytes apart, so that each MCentral.lock 103 // gets its own cache line. 104 central [_NumSizeClasses]struct { 105 mcentral mcentral 106 pad [sys.CacheLineSize]byte 107 } 108 109 spanalloc fixalloc // allocator for span* 110 cachealloc fixalloc // allocator for mcache* 111 treapalloc fixalloc // allocator for treapNodes* used by large objects 112 specialfinalizeralloc fixalloc // allocator for specialfinalizer* 113 specialprofilealloc fixalloc // allocator for specialprofile* 114 speciallock mutex // lock for special record allocators. 115 } 116 117 var mheap_ mheap 118 119 // An MSpan is a run of pages. 120 // 121 // When a MSpan is in the heap free list, state == MSpanFree 122 // and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span. 123 // 124 // When a MSpan is allocated, state == MSpanInUse or MSpanManual 125 // and heapmap(i) == span for all s->start <= i < s->start+s->npages. 126 127 // Every MSpan is in one doubly-linked list, 128 // either one of the MHeap's free lists or one of the 129 // MCentral's span lists. 130 131 // An MSpan representing actual memory has state _MSpanInUse, 132 // _MSpanManual, or _MSpanFree. Transitions between these states are 133 // constrained as follows: 134 // 135 // * A span may transition from free to in-use or manual during any GC 136 // phase. 137 // 138 // * During sweeping (gcphase == _GCoff), a span may transition from 139 // in-use to free (as a result of sweeping) or manual to free (as a 140 // result of stacks being freed). 141 // 142 // * During GC (gcphase != _GCoff), a span *must not* transition from 143 // manual or in-use to free. Because concurrent GC may read a pointer 144 // and then look up its span, the span state must be monotonic. 145 type mSpanState uint8 146 147 const ( 148 _MSpanDead mSpanState = iota 149 _MSpanInUse // allocated for garbage collected heap 150 _MSpanManual // allocated for manual management (e.g., stack allocator) 151 _MSpanFree 152 ) 153 154 // mSpanStateNames are the names of the span states, indexed by 155 // mSpanState. 156 var mSpanStateNames = []string{ 157 "_MSpanDead", 158 "_MSpanInUse", 159 "_MSpanManual", 160 "_MSpanFree", 161 } 162 163 // mSpanList heads a linked list of spans. 164 // 165 //go:notinheap 166 type mSpanList struct { 167 first *mspan // first span in list, or nil if none 168 last *mspan // last span in list, or nil if none 169 } 170 171 //go:notinheap 172 type mspan struct { 173 next *mspan // next span in list, or nil if none 174 prev *mspan // previous span in list, or nil if none 175 list *mSpanList // For debugging. TODO: Remove. 176 177 startAddr uintptr // address of first byte of span aka s.base() 178 npages uintptr // number of pages in span 179 180 manualFreeList gclinkptr // list of free objects in _MSpanManual spans 181 182 // freeindex is the slot index between 0 and nelems at which to begin scanning 183 // for the next free object in this span. 184 // Each allocation scans allocBits starting at freeindex until it encounters a 0 185 // indicating a free object. freeindex is then adjusted so that subsequent scans begin 186 // just past the newly discovered free object. 187 // 188 // If freeindex == nelem, this span has no free objects. 189 // 190 // allocBits is a bitmap of objects in this span. 191 // If n >= freeindex and allocBits[n/8] & (1<<(n%8)) is 0 192 // then object n is free; 193 // otherwise, object n is allocated. Bits starting at nelem are 194 // undefined and should never be referenced. 195 // 196 // Object n starts at address n*elemsize + (start << pageShift). 197 freeindex uintptr 198 // TODO: Look up nelems from sizeclass and remove this field if it 199 // helps performance. 200 nelems uintptr // number of object in the span. 201 202 // Cache of the allocBits at freeindex. allocCache is shifted 203 // such that the lowest bit corresponds to the bit freeindex. 204 // allocCache holds the complement of allocBits, thus allowing 205 // ctz (count trailing zero) to use it directly. 206 // allocCache may contain bits beyond s.nelems; the caller must ignore 207 // these. 208 allocCache uint64 209 210 // allocBits and gcmarkBits hold pointers to a span's mark and 211 // allocation bits. The pointers are 8 byte aligned. 212 // There are three arenas where this data is held. 213 // free: Dirty arenas that are no longer accessed 214 // and can be reused. 215 // next: Holds information to be used in the next GC cycle. 216 // current: Information being used during this GC cycle. 217 // previous: Information being used during the last GC cycle. 218 // A new GC cycle starts with the call to finishsweep_m. 219 // finishsweep_m moves the previous arena to the free arena, 220 // the current arena to the previous arena, and 221 // the next arena to the current arena. 222 // The next arena is populated as the spans request 223 // memory to hold gcmarkBits for the next GC cycle as well 224 // as allocBits for newly allocated spans. 225 // 226 // The pointer arithmetic is done "by hand" instead of using 227 // arrays to avoid bounds checks along critical performance 228 // paths. 229 // The sweep will free the old allocBits and set allocBits to the 230 // gcmarkBits. The gcmarkBits are replaced with a fresh zeroed 231 // out memory. 232 allocBits *gcBits 233 gcmarkBits *gcBits 234 235 // sweep generation: 236 // if sweepgen == h->sweepgen - 2, the span needs sweeping 237 // if sweepgen == h->sweepgen - 1, the span is currently being swept 238 // if sweepgen == h->sweepgen, the span is swept and ready to use 239 // h->sweepgen is incremented by 2 after every GC 240 241 sweepgen uint32 242 divMul uint16 // for divide by elemsize - divMagic.mul 243 baseMask uint16 // if non-0, elemsize is a power of 2, & this will get object allocation base 244 allocCount uint16 // number of allocated objects 245 sizeclass uint8 // size class 246 incache bool // being used by an mcache 247 state mSpanState // mspaninuse etc 248 needzero uint8 // needs to be zeroed before allocation 249 divShift uint8 // for divide by elemsize - divMagic.shift 250 divShift2 uint8 // for divide by elemsize - divMagic.shift2 251 elemsize uintptr // computed from sizeclass or from npages 252 unusedsince int64 // first time spotted by gc in mspanfree state 253 npreleased uintptr // number of pages released to the os 254 limit uintptr // end of data in span 255 speciallock mutex // guards specials list 256 specials *special // linked list of special records sorted by offset. 257 } 258 259 func (s *mspan) base() uintptr { 260 return s.startAddr 261 } 262 263 func (s *mspan) layout() (size, n, total uintptr) { 264 total = s.npages << _PageShift 265 size = s.elemsize 266 if size > 0 { 267 n = total / size 268 } 269 return 270 } 271 272 func recordspan(vh unsafe.Pointer, p unsafe.Pointer) { 273 h := (*mheap)(vh) 274 s := (*mspan)(p) 275 if len(h.allspans) >= cap(h.allspans) { 276 n := 64 * 1024 / sys.PtrSize 277 if n < cap(h.allspans)*3/2 { 278 n = cap(h.allspans) * 3 / 2 279 } 280 var new []*mspan 281 sp := (*slice)(unsafe.Pointer(&new)) 282 sp.array = sysAlloc(uintptr(n)*sys.PtrSize, &memstats.other_sys) 283 if sp.array == nil { 284 throw("runtime: cannot allocate memory") 285 } 286 sp.len = len(h.allspans) 287 sp.cap = n 288 if len(h.allspans) > 0 { 289 copy(new, h.allspans) 290 } 291 oldAllspans := h.allspans 292 h.allspans = new 293 if len(oldAllspans) != 0 { 294 sysFree(unsafe.Pointer(&oldAllspans[0]), uintptr(cap(oldAllspans))*unsafe.Sizeof(oldAllspans[0]), &memstats.other_sys) 295 } 296 } 297 h.allspans = append(h.allspans, s) 298 } 299 300 // inheap reports whether b is a pointer into a (potentially dead) heap object. 301 // It returns false for pointers into _MSpanManual spans. 302 // Non-preemptible because it is used by write barriers. 303 //go:nowritebarrier 304 //go:nosplit 305 func inheap(b uintptr) bool { 306 if b == 0 || b < mheap_.arena_start || b >= mheap_.arena_used { 307 return false 308 } 309 // Not a beginning of a block, consult span table to find the block beginning. 310 s := mheap_.spans[(b-mheap_.arena_start)>>_PageShift] 311 if s == nil || b < s.base() || b >= s.limit || s.state != mSpanInUse { 312 return false 313 } 314 return true 315 } 316 317 // inHeapOrStack is a variant of inheap that returns true for pointers 318 // into any allocated heap span. 319 // 320 //go:nowritebarrier 321 //go:nosplit 322 func inHeapOrStack(b uintptr) bool { 323 if b == 0 || b < mheap_.arena_start || b >= mheap_.arena_used { 324 return false 325 } 326 // Not a beginning of a block, consult span table to find the block beginning. 327 s := mheap_.spans[(b-mheap_.arena_start)>>_PageShift] 328 if s == nil || b < s.base() { 329 return false 330 } 331 switch s.state { 332 case mSpanInUse, _MSpanManual: 333 return b < s.limit 334 default: 335 return false 336 } 337 } 338 339 // TODO: spanOf and spanOfUnchecked are open-coded in a lot of places. 340 // Use the functions instead. 341 342 // spanOf returns the span of p. If p does not point into the heap or 343 // no span contains p, spanOf returns nil. 344 func spanOf(p uintptr) *mspan { 345 if p == 0 || p < mheap_.arena_start || p >= mheap_.arena_used { 346 return nil 347 } 348 return spanOfUnchecked(p) 349 } 350 351 // spanOfUnchecked is equivalent to spanOf, but the caller must ensure 352 // that p points into the heap (that is, mheap_.arena_start <= p < 353 // mheap_.arena_used). 354 func spanOfUnchecked(p uintptr) *mspan { 355 return mheap_.spans[(p-mheap_.arena_start)>>_PageShift] 356 } 357 358 func mlookup(v uintptr, base *uintptr, size *uintptr, sp **mspan) int32 { 359 _g_ := getg() 360 361 _g_.m.mcache.local_nlookup++ 362 if sys.PtrSize == 4 && _g_.m.mcache.local_nlookup >= 1<<30 { 363 // purge cache stats to prevent overflow 364 lock(&mheap_.lock) 365 purgecachedstats(_g_.m.mcache) 366 unlock(&mheap_.lock) 367 } 368 369 s := mheap_.lookupMaybe(unsafe.Pointer(v)) 370 if sp != nil { 371 *sp = s 372 } 373 if s == nil { 374 if base != nil { 375 *base = 0 376 } 377 if size != nil { 378 *size = 0 379 } 380 return 0 381 } 382 383 p := s.base() 384 if s.sizeclass == 0 { 385 // Large object. 386 if base != nil { 387 *base = p 388 } 389 if size != nil { 390 *size = s.npages << _PageShift 391 } 392 return 1 393 } 394 395 n := s.elemsize 396 if base != nil { 397 i := (v - p) / n 398 *base = p + i*n 399 } 400 if size != nil { 401 *size = n 402 } 403 404 return 1 405 } 406 407 // Initialize the heap. 408 func (h *mheap) init(spansStart, spansBytes uintptr) { 409 h.treapalloc.init(unsafe.Sizeof(treapNode{}), nil, nil, &memstats.other_sys) 410 h.spanalloc.init(unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys) 411 h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys) 412 h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys) 413 h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys) 414 415 // Don't zero mspan allocations. Background sweeping can 416 // inspect a span concurrently with allocating it, so it's 417 // important that the span's sweepgen survive across freeing 418 // and re-allocating a span to prevent background sweeping 419 // from improperly cas'ing it from 0. 420 // 421 // This is safe because mspan contains no heap pointers. 422 h.spanalloc.zero = false 423 424 // h->mapcache needs no init 425 for i := range h.free { 426 h.free[i].init() 427 h.busy[i].init() 428 } 429 430 h.busylarge.init() 431 for i := range h.central { 432 h.central[i].mcentral.init(int32(i)) 433 } 434 435 sp := (*slice)(unsafe.Pointer(&h.spans)) 436 sp.array = unsafe.Pointer(spansStart) 437 sp.len = 0 438 sp.cap = int(spansBytes / sys.PtrSize) 439 } 440 441 // setArenaUsed extends the usable arena to address arena_used and 442 // maps auxiliary VM regions for any newly usable arena space. 443 // 444 // racemap indicates that this memory should be managed by the race 445 // detector. racemap should be true unless this is covering a VM hole. 446 func (h *mheap) setArenaUsed(arena_used uintptr, racemap bool) { 447 // Map auxiliary structures *before* h.arena_used is updated. 448 // Waiting to update arena_used until after the memory has been mapped 449 // avoids faults when other threads try access these regions immediately 450 // after observing the change to arena_used. 451 452 // Map the bitmap. 453 h.mapBits(arena_used) 454 455 // Map spans array. 456 h.mapSpans(arena_used) 457 458 // Tell the race detector about the new heap memory. 459 if racemap && raceenabled { 460 racemapshadow(unsafe.Pointer(h.arena_used), arena_used-h.arena_used) 461 } 462 463 h.arena_used = arena_used 464 } 465 466 // mapSpans makes sure that the spans are mapped 467 // up to the new value of arena_used. 468 // 469 // Don't call this directly. Call mheap.setArenaUsed. 470 func (h *mheap) mapSpans(arena_used uintptr) { 471 // Map spans array, PageSize at a time. 472 n := arena_used 473 n -= h.arena_start 474 n = n / _PageSize * sys.PtrSize 475 n = round(n, physPageSize) 476 need := n / unsafe.Sizeof(h.spans[0]) 477 have := uintptr(len(h.spans)) 478 if have >= need { 479 return 480 } 481 h.spans = h.spans[:need] 482 sysMap(unsafe.Pointer(&h.spans[have]), (need-have)*unsafe.Sizeof(h.spans[0]), h.arena_reserved, &memstats.other_sys) 483 } 484 485 // Sweeps spans in list until reclaims at least npages into heap. 486 // Returns the actual number of pages reclaimed. 487 func (h *mheap) reclaimList(list *mSpanList, npages uintptr) uintptr { 488 n := uintptr(0) 489 sg := mheap_.sweepgen 490 retry: 491 for s := list.first; s != nil; s = s.next { 492 if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { 493 list.remove(s) 494 // swept spans are at the end of the list 495 list.insertBack(s) // Puts it back on a busy list. s is not in the treap at this point. 496 unlock(&h.lock) 497 snpages := s.npages 498 if s.sweep(false) { 499 n += snpages 500 } 501 lock(&h.lock) 502 if n >= npages { 503 return n 504 } 505 // the span could have been moved elsewhere 506 goto retry 507 } 508 if s.sweepgen == sg-1 { 509 // the span is being sweept by background sweeper, skip 510 continue 511 } 512 // already swept empty span, 513 // all subsequent ones must also be either swept or in process of sweeping 514 break 515 } 516 return n 517 } 518 519 // Sweeps and reclaims at least npage pages into heap. 520 // Called before allocating npage pages. 521 func (h *mheap) reclaim(npage uintptr) { 522 // First try to sweep busy spans with large objects of size >= npage, 523 // this has good chances of reclaiming the necessary space. 524 for i := int(npage); i < len(h.busy); i++ { 525 if h.reclaimList(&h.busy[i], npage) != 0 { 526 return // Bingo! 527 } 528 } 529 530 // Then -- even larger objects. 531 if h.reclaimList(&h.busylarge, npage) != 0 { 532 return // Bingo! 533 } 534 535 // Now try smaller objects. 536 // One such object is not enough, so we need to reclaim several of them. 537 reclaimed := uintptr(0) 538 for i := 0; i < int(npage) && i < len(h.busy); i++ { 539 reclaimed += h.reclaimList(&h.busy[i], npage-reclaimed) 540 if reclaimed >= npage { 541 return 542 } 543 } 544 545 // Now sweep everything that is not yet swept. 546 unlock(&h.lock) 547 for { 548 n := sweepone() 549 if n == ^uintptr(0) { // all spans are swept 550 break 551 } 552 reclaimed += n 553 if reclaimed >= npage { 554 break 555 } 556 } 557 lock(&h.lock) 558 } 559 560 // Allocate a new span of npage pages from the heap for GC'd memory 561 // and record its size class in the HeapMap and HeapMapCache. 562 func (h *mheap) alloc_m(npage uintptr, sizeclass int32, large bool) *mspan { 563 _g_ := getg() 564 if _g_ != _g_.m.g0 { 565 throw("_mheap_alloc not on g0 stack") 566 } 567 lock(&h.lock) 568 569 // To prevent excessive heap growth, before allocating n pages 570 // we need to sweep and reclaim at least n pages. 571 if h.sweepdone == 0 { 572 // TODO(austin): This tends to sweep a large number of 573 // spans in order to find a few completely free spans 574 // (for example, in the garbage benchmark, this sweeps 575 // ~30x the number of pages its trying to allocate). 576 // If GC kept a bit for whether there were any marks 577 // in a span, we could release these free spans 578 // at the end of GC and eliminate this entirely. 579 h.reclaim(npage) 580 } 581 582 // transfer stats from cache to global 583 memstats.heap_scan += uint64(_g_.m.mcache.local_scan) 584 _g_.m.mcache.local_scan = 0 585 memstats.tinyallocs += uint64(_g_.m.mcache.local_tinyallocs) 586 _g_.m.mcache.local_tinyallocs = 0 587 588 s := h.allocSpanLocked(npage, &memstats.heap_inuse) 589 if s != nil { 590 // Record span info, because gc needs to be 591 // able to map interior pointer to containing span. 592 atomic.Store(&s.sweepgen, h.sweepgen) 593 h.sweepSpans[h.sweepgen/2%2].push(s) // Add to swept in-use list. 594 s.state = _MSpanInUse 595 s.allocCount = 0 596 s.sizeclass = uint8(sizeclass) 597 if sizeclass == 0 { 598 s.elemsize = s.npages << _PageShift 599 s.divShift = 0 600 s.divMul = 0 601 s.divShift2 = 0 602 s.baseMask = 0 603 } else { 604 s.elemsize = uintptr(class_to_size[sizeclass]) 605 m := &class_to_divmagic[sizeclass] 606 s.divShift = m.shift 607 s.divMul = m.mul 608 s.divShift2 = m.shift2 609 s.baseMask = m.baseMask 610 } 611 612 // update stats, sweep lists 613 h.pagesInUse += uint64(npage) 614 if large { 615 memstats.heap_objects++ 616 mheap_.largealloc += uint64(s.elemsize) 617 mheap_.nlargealloc++ 618 atomic.Xadd64(&memstats.heap_live, int64(npage<<_PageShift)) 619 // Swept spans are at the end of lists. 620 if s.npages < uintptr(len(h.busy)) { 621 h.busy[s.npages].insertBack(s) 622 } else { 623 h.busylarge.insertBack(s) 624 } 625 } 626 } 627 // heap_scan and heap_live were updated. 628 if gcBlackenEnabled != 0 { 629 gcController.revise() 630 } 631 632 if trace.enabled { 633 traceHeapAlloc() 634 } 635 636 // h.spans is accessed concurrently without synchronization 637 // from other threads. Hence, there must be a store/store 638 // barrier here to ensure the writes to h.spans above happen 639 // before the caller can publish a pointer p to an object 640 // allocated from s. As soon as this happens, the garbage 641 // collector running on another processor could read p and 642 // look up s in h.spans. The unlock acts as the barrier to 643 // order these writes. On the read side, the data dependency 644 // between p and the index in h.spans orders the reads. 645 unlock(&h.lock) 646 return s 647 } 648 649 func (h *mheap) alloc(npage uintptr, sizeclass int32, large bool, needzero bool) *mspan { 650 // Don't do any operations that lock the heap on the G stack. 651 // It might trigger stack growth, and the stack growth code needs 652 // to be able to allocate heap. 653 var s *mspan 654 systemstack(func() { 655 s = h.alloc_m(npage, sizeclass, large) 656 }) 657 658 if s != nil { 659 if needzero && s.needzero != 0 { 660 memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift) 661 } 662 s.needzero = 0 663 } 664 return s 665 } 666 667 // allocManual allocates a manually-managed span of npage pages. 668 // allocManual returns nil if allocation fails. 669 // 670 // allocManual adds the bytes used to *stat, which should be a 671 // memstats in-use field. Unlike allocations in the GC'd heap, the 672 // allocation does *not* count toward heap_inuse or heap_sys. 673 // 674 // The memory backing the returned span may not be zeroed if 675 // span.needzero is set. 676 // 677 // allocManual must be called on the system stack to prevent stack 678 // growth. Since this is used by the stack allocator, stack growth 679 // during allocManual would self-deadlock. 680 // 681 //go:systemstack 682 func (h *mheap) allocManual(npage uintptr, stat *uint64) *mspan { 683 lock(&h.lock) 684 s := h.allocSpanLocked(npage, stat) 685 if s != nil { 686 s.state = _MSpanManual 687 s.manualFreeList = 0 688 s.allocCount = 0 689 s.sizeclass = 0 690 s.nelems = 0 691 s.elemsize = 0 692 s.limit = s.base() + s.npages<<_PageShift 693 // Manually manged memory doesn't count toward heap_sys. 694 memstats.heap_sys -= uint64(s.npages << _PageShift) 695 } 696 697 // This unlock acts as a release barrier. See mheap.alloc_m. 698 unlock(&h.lock) 699 700 return s 701 } 702 703 // Allocates a span of the given size. h must be locked. 704 // The returned span has been removed from the 705 // free list, but its state is still MSpanFree. 706 func (h *mheap) allocSpanLocked(npage uintptr, stat *uint64) *mspan { 707 var list *mSpanList 708 var s *mspan 709 710 // Try in fixed-size lists up to max. 711 for i := int(npage); i < len(h.free); i++ { 712 list = &h.free[i] 713 if !list.isEmpty() { 714 s = list.first 715 list.remove(s) 716 goto HaveSpan 717 } 718 } 719 // Best fit in list of large spans. 720 s = h.allocLarge(npage) // allocLarge removed s from h.freelarge for us 721 if s == nil { 722 if !h.grow(npage) { 723 return nil 724 } 725 s = h.allocLarge(npage) 726 if s == nil { 727 return nil 728 } 729 } 730 731 HaveSpan: 732 // Mark span in use. 733 if s.state != _MSpanFree { 734 throw("MHeap_AllocLocked - MSpan not free") 735 } 736 if s.npages < npage { 737 throw("MHeap_AllocLocked - bad npages") 738 } 739 if s.npreleased > 0 { 740 sysUsed(unsafe.Pointer(s.base()), s.npages<<_PageShift) 741 memstats.heap_released -= uint64(s.npreleased << _PageShift) 742 s.npreleased = 0 743 } 744 745 if s.npages > npage { 746 // Trim extra and put it back in the heap. 747 t := (*mspan)(h.spanalloc.alloc()) 748 t.init(s.base()+npage<<_PageShift, s.npages-npage) 749 s.npages = npage 750 p := (t.base() - h.arena_start) >> _PageShift 751 if p > 0 { 752 h.spans[p-1] = s 753 } 754 h.spans[p] = t 755 h.spans[p+t.npages-1] = t 756 t.needzero = s.needzero 757 s.state = _MSpanManual // prevent coalescing with s 758 t.state = _MSpanManual 759 h.freeSpanLocked(t, false, false, s.unusedsince) 760 s.state = _MSpanFree 761 } 762 s.unusedsince = 0 763 764 p := (s.base() - h.arena_start) >> _PageShift 765 for n := uintptr(0); n < npage; n++ { 766 h.spans[p+n] = s 767 } 768 769 *stat += uint64(npage << _PageShift) 770 memstats.heap_idle -= uint64(npage << _PageShift) 771 772 //println("spanalloc", hex(s.start<<_PageShift)) 773 if s.inList() { 774 throw("still in list") 775 } 776 return s 777 } 778 779 // Large spans have a minimum size of 1MByte. The maximum number of large spans to support 780 // 1TBytes is 1 million, experimentation using random sizes indicates that the depth of 781 // the tree is less that 2x that of a perfectly balanced tree. For 1TByte can be referenced 782 // by a perfectly balanced tree with a a depth of 20. Twice that is an acceptable 40. 783 func (h *mheap) isLargeSpan(npages uintptr) bool { 784 return npages >= uintptr(len(h.free)) 785 } 786 787 // Allocate a span of exactly npage pages from the treap of large spans. 788 func (h *mheap) allocLarge(npage uintptr) *mspan { 789 return bestFitTreap(&h.freelarge, npage) 790 } 791 792 // Search treap for smallest span with >= npage pages. 793 // If there are multiple smallest spans, select the one 794 // with the earliest starting address. 795 func bestFitTreap(treap *mTreap, npage uintptr) *mspan { 796 return treap.remove(npage) 797 } 798 799 // Try to add at least npage pages of memory to the heap, 800 // returning whether it worked. 801 // 802 // h must be locked. 803 func (h *mheap) grow(npage uintptr) bool { 804 // Ask for a big chunk, to reduce the number of mappings 805 // the operating system needs to track; also amortizes 806 // the overhead of an operating system mapping. 807 // Allocate a multiple of 64kB. 808 npage = round(npage, (64<<10)/_PageSize) 809 ask := npage << _PageShift 810 if ask < _HeapAllocChunk { 811 ask = _HeapAllocChunk 812 } 813 814 v := h.sysAlloc(ask) 815 if v == nil { 816 if ask > npage<<_PageShift { 817 ask = npage << _PageShift 818 v = h.sysAlloc(ask) 819 } 820 if v == nil { 821 print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n") 822 return false 823 } 824 } 825 826 // Create a fake "in use" span and free it, so that the 827 // right coalescing happens. 828 s := (*mspan)(h.spanalloc.alloc()) 829 s.init(uintptr(v), ask>>_PageShift) 830 p := (s.base() - h.arena_start) >> _PageShift 831 for i := p; i < p+s.npages; i++ { 832 h.spans[i] = s 833 } 834 atomic.Store(&s.sweepgen, h.sweepgen) 835 s.state = _MSpanInUse 836 h.pagesInUse += uint64(s.npages) 837 h.freeSpanLocked(s, false, true, 0) 838 return true 839 } 840 841 // Look up the span at the given address. 842 // Address is guaranteed to be in map 843 // and is guaranteed to be start or end of span. 844 func (h *mheap) lookup(v unsafe.Pointer) *mspan { 845 p := uintptr(v) 846 p -= h.arena_start 847 return h.spans[p>>_PageShift] 848 } 849 850 // Look up the span at the given address. 851 // Address is *not* guaranteed to be in map 852 // and may be anywhere in the span. 853 // Map entries for the middle of a span are only 854 // valid for allocated spans. Free spans may have 855 // other garbage in their middles, so we have to 856 // check for that. 857 func (h *mheap) lookupMaybe(v unsafe.Pointer) *mspan { 858 if uintptr(v) < h.arena_start || uintptr(v) >= h.arena_used { 859 return nil 860 } 861 s := h.spans[(uintptr(v)-h.arena_start)>>_PageShift] 862 if s == nil || uintptr(v) < s.base() || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != _MSpanInUse { 863 return nil 864 } 865 return s 866 } 867 868 // Free the span back into the heap. 869 func (h *mheap) freeSpan(s *mspan, acct int32) { 870 systemstack(func() { 871 mp := getg().m 872 lock(&h.lock) 873 memstats.heap_scan += uint64(mp.mcache.local_scan) 874 mp.mcache.local_scan = 0 875 memstats.tinyallocs += uint64(mp.mcache.local_tinyallocs) 876 mp.mcache.local_tinyallocs = 0 877 if msanenabled { 878 // Tell msan that this entire span is no longer in use. 879 base := unsafe.Pointer(s.base()) 880 bytes := s.npages << _PageShift 881 msanfree(base, bytes) 882 } 883 if acct != 0 { 884 memstats.heap_objects-- 885 } 886 if gcBlackenEnabled != 0 { 887 // heap_scan changed. 888 gcController.revise() 889 } 890 h.freeSpanLocked(s, true, true, 0) 891 unlock(&h.lock) 892 }) 893 } 894 895 // freeManual frees a manually-managed span returned by allocManual. 896 // stat must be the same as the stat passed to the allocManual that 897 // allocated s. 898 // 899 // This must only be called when gcphase == _GCoff. See mSpanState for 900 // an explanation. 901 // 902 // freeManual must be called on the system stack to prevent stack 903 // growth, just like allocManual. 904 // 905 //go:systemstack 906 func (h *mheap) freeManual(s *mspan, stat *uint64) { 907 s.needzero = 1 908 lock(&h.lock) 909 *stat -= uint64(s.npages << _PageShift) 910 memstats.heap_sys += uint64(s.npages << _PageShift) 911 h.freeSpanLocked(s, false, true, 0) 912 unlock(&h.lock) 913 } 914 915 // s must be on a busy list (h.busy or h.busylarge) or unlinked. 916 func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince int64) { 917 switch s.state { 918 case _MSpanManual: 919 if s.allocCount != 0 { 920 throw("MHeap_FreeSpanLocked - invalid stack free") 921 } 922 case _MSpanInUse: 923 if s.allocCount != 0 || s.sweepgen != h.sweepgen { 924 print("MHeap_FreeSpanLocked - span ", s, " ptr ", hex(s.base()), " allocCount ", s.allocCount, " sweepgen ", s.sweepgen, "/", h.sweepgen, "\n") 925 throw("MHeap_FreeSpanLocked - invalid free") 926 } 927 h.pagesInUse -= uint64(s.npages) 928 default: 929 throw("MHeap_FreeSpanLocked - invalid span state") 930 } 931 932 if acctinuse { 933 memstats.heap_inuse -= uint64(s.npages << _PageShift) 934 } 935 if acctidle { 936 memstats.heap_idle += uint64(s.npages << _PageShift) 937 } 938 s.state = _MSpanFree 939 if s.inList() { 940 h.busyList(s.npages).remove(s) 941 } 942 943 // Stamp newly unused spans. The scavenger will use that 944 // info to potentially give back some pages to the OS. 945 s.unusedsince = unusedsince 946 if unusedsince == 0 { 947 s.unusedsince = nanotime() 948 } 949 s.npreleased = 0 950 951 // Coalesce with earlier, later spans. 952 p := (s.base() - h.arena_start) >> _PageShift 953 if p > 0 { 954 before := h.spans[p-1] 955 if before != nil && before.state == _MSpanFree { 956 // Now adjust s. 957 s.startAddr = before.startAddr 958 s.npages += before.npages 959 s.npreleased = before.npreleased // absorb released pages 960 s.needzero |= before.needzero 961 p -= before.npages 962 h.spans[p] = s 963 // The size is potentially changing so the treap needs to delete adjacent nodes and 964 // insert back as a combined node. 965 if h.isLargeSpan(before.npages) { 966 // We have a t, it is large so it has to be in the treap so we can remove it. 967 h.freelarge.removeSpan(before) 968 } else { 969 h.freeList(before.npages).remove(before) 970 } 971 before.state = _MSpanDead 972 h.spanalloc.free(unsafe.Pointer(before)) 973 } 974 } 975 976 // Now check to see if next (greater addresses) span is free and can be coalesced. 977 if (p + s.npages) < uintptr(len(h.spans)) { 978 after := h.spans[p+s.npages] 979 if after != nil && after.state == _MSpanFree { 980 s.npages += after.npages 981 s.npreleased += after.npreleased 982 s.needzero |= after.needzero 983 h.spans[p+s.npages-1] = s 984 if h.isLargeSpan(after.npages) { 985 h.freelarge.removeSpan(after) 986 } else { 987 h.freeList(after.npages).remove(after) 988 } 989 after.state = _MSpanDead 990 h.spanalloc.free(unsafe.Pointer(after)) 991 } 992 } 993 994 // Insert s into appropriate list or treap. 995 if h.isLargeSpan(s.npages) { 996 h.freelarge.insert(s) 997 } else { 998 h.freeList(s.npages).insert(s) 999 } 1000 } 1001 1002 func (h *mheap) freeList(npages uintptr) *mSpanList { 1003 return &h.free[npages] 1004 } 1005 1006 func (h *mheap) busyList(npages uintptr) *mSpanList { 1007 if npages < uintptr(len(h.busy)) { 1008 return &h.busy[npages] 1009 } 1010 return &h.busylarge 1011 } 1012 1013 func scavengeTreapNode(t *treapNode, now, limit uint64) uintptr { 1014 s := t.spanKey 1015 var sumreleased uintptr 1016 if (now-uint64(s.unusedsince)) > limit && s.npreleased != s.npages { 1017 start := s.base() 1018 end := start + s.npages<<_PageShift 1019 if physPageSize > _PageSize { 1020 // We can only release pages in 1021 // physPageSize blocks, so round start 1022 // and end in. (Otherwise, madvise 1023 // will round them *out* and release 1024 // more memory than we want.) 1025 start = (start + physPageSize - 1) &^ (physPageSize - 1) 1026 end &^= physPageSize - 1 1027 if end <= start { 1028 // start and end don't span a 1029 // whole physical page. 1030 return sumreleased 1031 } 1032 } 1033 len := end - start 1034 released := len - (s.npreleased << _PageShift) 1035 if physPageSize > _PageSize && released == 0 { 1036 return sumreleased 1037 } 1038 memstats.heap_released += uint64(released) 1039 sumreleased += released 1040 s.npreleased = len >> _PageShift 1041 sysUnused(unsafe.Pointer(start), len) 1042 } 1043 return sumreleased 1044 } 1045 1046 func scavengelist(list *mSpanList, now, limit uint64) uintptr { 1047 if list.isEmpty() { 1048 return 0 1049 } 1050 1051 var sumreleased uintptr 1052 for s := list.first; s != nil; s = s.next { 1053 if (now-uint64(s.unusedsince)) > limit && s.npreleased != s.npages { 1054 start := s.base() 1055 end := start + s.npages<<_PageShift 1056 if physPageSize > _PageSize { 1057 // We can only release pages in 1058 // physPageSize blocks, so round start 1059 // and end in. (Otherwise, madvise 1060 // will round them *out* and release 1061 // more memory than we want.) 1062 start = (start + physPageSize - 1) &^ (physPageSize - 1) 1063 end &^= physPageSize - 1 1064 if end <= start { 1065 // start and end don't span a 1066 // whole physical page. 1067 continue 1068 } 1069 } 1070 len := end - start 1071 1072 released := len - (s.npreleased << _PageShift) 1073 if physPageSize > _PageSize && released == 0 { 1074 continue 1075 } 1076 memstats.heap_released += uint64(released) 1077 sumreleased += released 1078 s.npreleased = len >> _PageShift 1079 sysUnused(unsafe.Pointer(start), len) 1080 } 1081 } 1082 return sumreleased 1083 } 1084 1085 func (h *mheap) scavenge(k int32, now, limit uint64) { 1086 // Disallow malloc or panic while holding the heap lock. We do 1087 // this here because this is an non-mallocgc entry-point to 1088 // the mheap API. 1089 gp := getg() 1090 gp.m.mallocing++ 1091 lock(&h.lock) 1092 var sumreleased uintptr 1093 for i := 0; i < len(h.free); i++ { 1094 sumreleased += scavengelist(&h.free[i], now, limit) 1095 } 1096 sumreleased += scavengetreap(h.freelarge.treap, now, limit) 1097 unlock(&h.lock) 1098 gp.m.mallocing-- 1099 1100 if debug.gctrace > 0 { 1101 if sumreleased > 0 { 1102 print("scvg", k, ": ", sumreleased>>20, " MB released\n") 1103 } 1104 print("scvg", k, ": inuse: ", memstats.heap_inuse>>20, ", idle: ", memstats.heap_idle>>20, ", sys: ", memstats.heap_sys>>20, ", released: ", memstats.heap_released>>20, ", consumed: ", (memstats.heap_sys-memstats.heap_released)>>20, " (MB)\n") 1105 } 1106 } 1107 1108 //go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory 1109 func runtime_debug_freeOSMemory() { 1110 GC() 1111 systemstack(func() { mheap_.scavenge(-1, ^uint64(0), 0) }) 1112 } 1113 1114 // Initialize a new span with the given start and npages. 1115 func (span *mspan) init(base uintptr, npages uintptr) { 1116 // span is *not* zeroed. 1117 span.next = nil 1118 span.prev = nil 1119 span.list = nil 1120 span.startAddr = base 1121 span.npages = npages 1122 span.allocCount = 0 1123 span.sizeclass = 0 1124 span.incache = false 1125 span.elemsize = 0 1126 span.state = _MSpanDead 1127 span.unusedsince = 0 1128 span.npreleased = 0 1129 span.speciallock.key = 0 1130 span.specials = nil 1131 span.needzero = 0 1132 span.freeindex = 0 1133 span.allocBits = nil 1134 span.gcmarkBits = nil 1135 } 1136 1137 func (span *mspan) inList() bool { 1138 return span.list != nil 1139 } 1140 1141 // Initialize an empty doubly-linked list. 1142 func (list *mSpanList) init() { 1143 list.first = nil 1144 list.last = nil 1145 } 1146 1147 func (list *mSpanList) remove(span *mspan) { 1148 if span.list != list { 1149 print("runtime: failed MSpanList_Remove span.npages=", span.npages, 1150 " span=", span, " prev=", span.prev, " span.list=", span.list, " list=", list, "\n") 1151 throw("MSpanList_Remove") 1152 } 1153 if list.first == span { 1154 list.first = span.next 1155 } else { 1156 span.prev.next = span.next 1157 } 1158 if list.last == span { 1159 list.last = span.prev 1160 } else { 1161 span.next.prev = span.prev 1162 } 1163 span.next = nil 1164 span.prev = nil 1165 span.list = nil 1166 } 1167 1168 func (list *mSpanList) isEmpty() bool { 1169 return list.first == nil 1170 } 1171 1172 func (list *mSpanList) insert(span *mspan) { 1173 if span.next != nil || span.prev != nil || span.list != nil { 1174 println("runtime: failed MSpanList_Insert", span, span.next, span.prev, span.list) 1175 throw("MSpanList_Insert") 1176 } 1177 span.next = list.first 1178 if list.first != nil { 1179 // The list contains at least one span; link it in. 1180 // The last span in the list doesn't change. 1181 list.first.prev = span 1182 } else { 1183 // The list contains no spans, so this is also the last span. 1184 list.last = span 1185 } 1186 list.first = span 1187 span.list = list 1188 } 1189 1190 func (list *mSpanList) insertBack(span *mspan) { 1191 if span.next != nil || span.prev != nil || span.list != nil { 1192 println("runtime: failed MSpanList_InsertBack", span, span.next, span.prev, span.list) 1193 throw("MSpanList_InsertBack") 1194 } 1195 span.prev = list.last 1196 if list.last != nil { 1197 // The list contains at least one span. 1198 list.last.next = span 1199 } else { 1200 // The list contains no spans, so this is also the first span. 1201 list.first = span 1202 } 1203 list.last = span 1204 span.list = list 1205 } 1206 1207 // takeAll removes all spans from other and inserts them at the front 1208 // of list. 1209 func (list *mSpanList) takeAll(other *mSpanList) { 1210 if other.isEmpty() { 1211 return 1212 } 1213 1214 // Reparent everything in other to list. 1215 for s := other.first; s != nil; s = s.next { 1216 s.list = list 1217 } 1218 1219 // Concatenate the lists. 1220 if list.isEmpty() { 1221 *list = *other 1222 } else { 1223 // Neither list is empty. Put other before list. 1224 other.last.next = list.first 1225 list.first.prev = other.last 1226 list.first = other.first 1227 } 1228 1229 other.first, other.last = nil, nil 1230 } 1231 1232 const ( 1233 _KindSpecialFinalizer = 1 1234 _KindSpecialProfile = 2 1235 // Note: The finalizer special must be first because if we're freeing 1236 // an object, a finalizer special will cause the freeing operation 1237 // to abort, and we want to keep the other special records around 1238 // if that happens. 1239 ) 1240 1241 //go:notinheap 1242 type special struct { 1243 next *special // linked list in span 1244 offset uint16 // span offset of object 1245 kind byte // kind of special 1246 } 1247 1248 // Adds the special record s to the list of special records for 1249 // the object p. All fields of s should be filled in except for 1250 // offset & next, which this routine will fill in. 1251 // Returns true if the special was successfully added, false otherwise. 1252 // (The add will fail only if a record with the same p and s->kind 1253 // already exists.) 1254 func addspecial(p unsafe.Pointer, s *special) bool { 1255 span := mheap_.lookupMaybe(p) 1256 if span == nil { 1257 throw("addspecial on invalid pointer") 1258 } 1259 1260 // Ensure that the span is swept. 1261 // Sweeping accesses the specials list w/o locks, so we have 1262 // to synchronize with it. And it's just much safer. 1263 mp := acquirem() 1264 span.ensureSwept() 1265 1266 offset := uintptr(p) - span.base() 1267 kind := s.kind 1268 1269 lock(&span.speciallock) 1270 1271 // Find splice point, check for existing record. 1272 t := &span.specials 1273 for { 1274 x := *t 1275 if x == nil { 1276 break 1277 } 1278 if offset == uintptr(x.offset) && kind == x.kind { 1279 unlock(&span.speciallock) 1280 releasem(mp) 1281 return false // already exists 1282 } 1283 if offset < uintptr(x.offset) || (offset == uintptr(x.offset) && kind < x.kind) { 1284 break 1285 } 1286 t = &x.next 1287 } 1288 1289 // Splice in record, fill in offset. 1290 s.offset = uint16(offset) 1291 s.next = *t 1292 *t = s 1293 unlock(&span.speciallock) 1294 releasem(mp) 1295 1296 return true 1297 } 1298 1299 // Removes the Special record of the given kind for the object p. 1300 // Returns the record if the record existed, nil otherwise. 1301 // The caller must FixAlloc_Free the result. 1302 func removespecial(p unsafe.Pointer, kind uint8) *special { 1303 span := mheap_.lookupMaybe(p) 1304 if span == nil { 1305 throw("removespecial on invalid pointer") 1306 } 1307 1308 // Ensure that the span is swept. 1309 // Sweeping accesses the specials list w/o locks, so we have 1310 // to synchronize with it. And it's just much safer. 1311 mp := acquirem() 1312 span.ensureSwept() 1313 1314 offset := uintptr(p) - span.base() 1315 1316 lock(&span.speciallock) 1317 t := &span.specials 1318 for { 1319 s := *t 1320 if s == nil { 1321 break 1322 } 1323 // This function is used for finalizers only, so we don't check for 1324 // "interior" specials (p must be exactly equal to s->offset). 1325 if offset == uintptr(s.offset) && kind == s.kind { 1326 *t = s.next 1327 unlock(&span.speciallock) 1328 releasem(mp) 1329 return s 1330 } 1331 t = &s.next 1332 } 1333 unlock(&span.speciallock) 1334 releasem(mp) 1335 return nil 1336 } 1337 1338 // The described object has a finalizer set for it. 1339 // 1340 // specialfinalizer is allocated from non-GC'd memory, so any heap 1341 // pointers must be specially handled. 1342 // 1343 //go:notinheap 1344 type specialfinalizer struct { 1345 special special 1346 fn *funcval // May be a heap pointer. 1347 nret uintptr 1348 fint *_type // May be a heap pointer, but always live. 1349 ot *ptrtype // May be a heap pointer, but always live. 1350 } 1351 1352 // Adds a finalizer to the object p. Returns true if it succeeded. 1353 func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *ptrtype) bool { 1354 lock(&mheap_.speciallock) 1355 s := (*specialfinalizer)(mheap_.specialfinalizeralloc.alloc()) 1356 unlock(&mheap_.speciallock) 1357 s.special.kind = _KindSpecialFinalizer 1358 s.fn = f 1359 s.nret = nret 1360 s.fint = fint 1361 s.ot = ot 1362 if addspecial(p, &s.special) { 1363 // This is responsible for maintaining the same 1364 // GC-related invariants as markrootSpans in any 1365 // situation where it's possible that markrootSpans 1366 // has already run but mark termination hasn't yet. 1367 if gcphase != _GCoff { 1368 _, base, _ := findObject(p) 1369 mp := acquirem() 1370 gcw := &mp.p.ptr().gcw 1371 // Mark everything reachable from the object 1372 // so it's retained for the finalizer. 1373 scanobject(uintptr(base), gcw) 1374 // Mark the finalizer itself, since the 1375 // special isn't part of the GC'd heap. 1376 scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw) 1377 if gcBlackenPromptly { 1378 gcw.dispose() 1379 } 1380 releasem(mp) 1381 } 1382 return true 1383 } 1384 1385 // There was an old finalizer 1386 lock(&mheap_.speciallock) 1387 mheap_.specialfinalizeralloc.free(unsafe.Pointer(s)) 1388 unlock(&mheap_.speciallock) 1389 return false 1390 } 1391 1392 // Removes the finalizer (if any) from the object p. 1393 func removefinalizer(p unsafe.Pointer) { 1394 s := (*specialfinalizer)(unsafe.Pointer(removespecial(p, _KindSpecialFinalizer))) 1395 if s == nil { 1396 return // there wasn't a finalizer to remove 1397 } 1398 lock(&mheap_.speciallock) 1399 mheap_.specialfinalizeralloc.free(unsafe.Pointer(s)) 1400 unlock(&mheap_.speciallock) 1401 } 1402 1403 // The described object is being heap profiled. 1404 // 1405 //go:notinheap 1406 type specialprofile struct { 1407 special special 1408 b *bucket 1409 } 1410 1411 // Set the heap profile bucket associated with addr to b. 1412 func setprofilebucket(p unsafe.Pointer, b *bucket) { 1413 lock(&mheap_.speciallock) 1414 s := (*specialprofile)(mheap_.specialprofilealloc.alloc()) 1415 unlock(&mheap_.speciallock) 1416 s.special.kind = _KindSpecialProfile 1417 s.b = b 1418 if !addspecial(p, &s.special) { 1419 throw("setprofilebucket: profile already set") 1420 } 1421 } 1422 1423 // Do whatever cleanup needs to be done to deallocate s. It has 1424 // already been unlinked from the MSpan specials list. 1425 func freespecial(s *special, p unsafe.Pointer, size uintptr) { 1426 switch s.kind { 1427 case _KindSpecialFinalizer: 1428 sf := (*specialfinalizer)(unsafe.Pointer(s)) 1429 queuefinalizer(p, sf.fn, sf.nret, sf.fint, sf.ot) 1430 lock(&mheap_.speciallock) 1431 mheap_.specialfinalizeralloc.free(unsafe.Pointer(sf)) 1432 unlock(&mheap_.speciallock) 1433 case _KindSpecialProfile: 1434 sp := (*specialprofile)(unsafe.Pointer(s)) 1435 mProf_Free(sp.b, size) 1436 lock(&mheap_.speciallock) 1437 mheap_.specialprofilealloc.free(unsafe.Pointer(sp)) 1438 unlock(&mheap_.speciallock) 1439 default: 1440 throw("bad special kind") 1441 panic("not reached") 1442 } 1443 } 1444 1445 // gcBits is an alloc/mark bitmap. This is always used as *gcBits. 1446 // 1447 //go:notinheap 1448 type gcBits uint8 1449 1450 // bytep returns a pointer to the n'th byte of b. 1451 func (b *gcBits) bytep(n uintptr) *uint8 { 1452 return addb((*uint8)(b), n) 1453 } 1454 1455 // bitp returns a pointer to the byte containing bit n and a mask for 1456 // selecting that bit from *bytep. 1457 func (b *gcBits) bitp(n uintptr) (bytep *uint8, mask uint8) { 1458 return b.bytep(n / 8), 1 << (n % 8) 1459 } 1460 1461 const gcBitsChunkBytes = uintptr(64 << 10) 1462 const gcBitsHeaderBytes = unsafe.Sizeof(gcBitsHeader{}) 1463 1464 type gcBitsHeader struct { 1465 free uintptr // free is the index into bits of the next free byte. 1466 next uintptr // *gcBits triggers recursive type bug. (issue 14620) 1467 } 1468 1469 //go:notinheap 1470 type gcBitsArena struct { 1471 // gcBitsHeader // side step recursive type bug (issue 14620) by including fields by hand. 1472 free uintptr // free is the index into bits of the next free byte; read/write atomically 1473 next *gcBitsArena 1474 bits [gcBitsChunkBytes - gcBitsHeaderBytes]gcBits 1475 } 1476 1477 var gcBitsArenas struct { 1478 lock mutex 1479 free *gcBitsArena 1480 next *gcBitsArena // Read atomically. Write atomically under lock. 1481 current *gcBitsArena 1482 previous *gcBitsArena 1483 } 1484 1485 // tryAlloc allocates from b or returns nil if b does not have enough room. 1486 // This is safe to call concurrently. 1487 func (b *gcBitsArena) tryAlloc(bytes uintptr) *gcBits { 1488 if b == nil || atomic.Loaduintptr(&b.free)+bytes > uintptr(len(b.bits)) { 1489 return nil 1490 } 1491 // Try to allocate from this block. 1492 end := atomic.Xadduintptr(&b.free, bytes) 1493 if end > uintptr(len(b.bits)) { 1494 return nil 1495 } 1496 // There was enough room. 1497 start := end - bytes 1498 return &b.bits[start] 1499 } 1500 1501 // newMarkBits returns a pointer to 8 byte aligned bytes 1502 // to be used for a span's mark bits. 1503 func newMarkBits(nelems uintptr) *gcBits { 1504 blocksNeeded := uintptr((nelems + 63) / 64) 1505 bytesNeeded := blocksNeeded * 8 1506 1507 // Try directly allocating from the current head arena. 1508 head := (*gcBitsArena)(atomic.Loadp(unsafe.Pointer(&gcBitsArenas.next))) 1509 if p := head.tryAlloc(bytesNeeded); p != nil { 1510 return p 1511 } 1512 1513 // There's not enough room in the head arena. We may need to 1514 // allocate a new arena. 1515 lock(&gcBitsArenas.lock) 1516 // Try the head arena again, since it may have changed. Now 1517 // that we hold the lock, the list head can't change, but its 1518 // free position still can. 1519 if p := gcBitsArenas.next.tryAlloc(bytesNeeded); p != nil { 1520 unlock(&gcBitsArenas.lock) 1521 return p 1522 } 1523 1524 // Allocate a new arena. This may temporarily drop the lock. 1525 fresh := newArenaMayUnlock() 1526 // If newArenaMayUnlock dropped the lock, another thread may 1527 // have put a fresh arena on the "next" list. Try allocating 1528 // from next again. 1529 if p := gcBitsArenas.next.tryAlloc(bytesNeeded); p != nil { 1530 // Put fresh back on the free list. 1531 // TODO: Mark it "already zeroed" 1532 fresh.next = gcBitsArenas.free 1533 gcBitsArenas.free = fresh 1534 unlock(&gcBitsArenas.lock) 1535 return p 1536 } 1537 1538 // Allocate from the fresh arena. We haven't linked it in yet, so 1539 // this cannot race and is guaranteed to succeed. 1540 p := fresh.tryAlloc(bytesNeeded) 1541 if p == nil { 1542 throw("markBits overflow") 1543 } 1544 1545 // Add the fresh arena to the "next" list. 1546 fresh.next = gcBitsArenas.next 1547 atomic.StorepNoWB(unsafe.Pointer(&gcBitsArenas.next), unsafe.Pointer(fresh)) 1548 1549 unlock(&gcBitsArenas.lock) 1550 return p 1551 } 1552 1553 // newAllocBits returns a pointer to 8 byte aligned bytes 1554 // to be used for this span's alloc bits. 1555 // newAllocBits is used to provide newly initialized spans 1556 // allocation bits. For spans not being initialized the 1557 // the mark bits are repurposed as allocation bits when 1558 // the span is swept. 1559 func newAllocBits(nelems uintptr) *gcBits { 1560 return newMarkBits(nelems) 1561 } 1562 1563 // nextMarkBitArenaEpoch establishes a new epoch for the arenas 1564 // holding the mark bits. The arenas are named relative to the 1565 // current GC cycle which is demarcated by the call to finishweep_m. 1566 // 1567 // All current spans have been swept. 1568 // During that sweep each span allocated room for its gcmarkBits in 1569 // gcBitsArenas.next block. gcBitsArenas.next becomes the gcBitsArenas.current 1570 // where the GC will mark objects and after each span is swept these bits 1571 // will be used to allocate objects. 1572 // gcBitsArenas.current becomes gcBitsArenas.previous where the span's 1573 // gcAllocBits live until all the spans have been swept during this GC cycle. 1574 // The span's sweep extinguishes all the references to gcBitsArenas.previous 1575 // by pointing gcAllocBits into the gcBitsArenas.current. 1576 // The gcBitsArenas.previous is released to the gcBitsArenas.free list. 1577 func nextMarkBitArenaEpoch() { 1578 lock(&gcBitsArenas.lock) 1579 if gcBitsArenas.previous != nil { 1580 if gcBitsArenas.free == nil { 1581 gcBitsArenas.free = gcBitsArenas.previous 1582 } else { 1583 // Find end of previous arenas. 1584 last := gcBitsArenas.previous 1585 for last = gcBitsArenas.previous; last.next != nil; last = last.next { 1586 } 1587 last.next = gcBitsArenas.free 1588 gcBitsArenas.free = gcBitsArenas.previous 1589 } 1590 } 1591 gcBitsArenas.previous = gcBitsArenas.current 1592 gcBitsArenas.current = gcBitsArenas.next 1593 atomic.StorepNoWB(unsafe.Pointer(&gcBitsArenas.next), nil) // newMarkBits calls newArena when needed 1594 unlock(&gcBitsArenas.lock) 1595 } 1596 1597 // newArenaMayUnlock allocates and zeroes a gcBits arena. 1598 // The caller must hold gcBitsArena.lock. This may temporarily release it. 1599 func newArenaMayUnlock() *gcBitsArena { 1600 var result *gcBitsArena 1601 if gcBitsArenas.free == nil { 1602 unlock(&gcBitsArenas.lock) 1603 result = (*gcBitsArena)(sysAlloc(gcBitsChunkBytes, &memstats.gc_sys)) 1604 if result == nil { 1605 throw("runtime: cannot allocate memory") 1606 } 1607 lock(&gcBitsArenas.lock) 1608 } else { 1609 result = gcBitsArenas.free 1610 gcBitsArenas.free = gcBitsArenas.free.next 1611 memclrNoHeapPointers(unsafe.Pointer(result), gcBitsChunkBytes) 1612 } 1613 result.next = nil 1614 // If result.bits is not 8 byte aligned adjust index so 1615 // that &result.bits[result.free] is 8 byte aligned. 1616 if uintptr(unsafe.Offsetof(gcBitsArena{}.bits))&7 == 0 { 1617 result.free = 0 1618 } else { 1619 result.free = 8 - (uintptr(unsafe.Pointer(&result.bits[0])) & 7) 1620 } 1621 return result 1622 }