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 9package runtime 10 11import ( 12 "internal/cpu" 13 "runtime/internal/atomic" 14 "runtime/internal/sys" 15 "unsafe" 16) 17 18const ( 19 // minPhysPageSize is a lower-bound on the physical page size. The 20 // true physical page size may be larger than this. In contrast, 21 // sys.PhysPageSize is an upper-bound on the physical page size. 22 minPhysPageSize = 4096 23 24 // maxPhysPageSize is the maximum page size the runtime supports. 25 maxPhysPageSize = 512 << 10 26 27 // maxPhysHugePageSize sets an upper-bound on the maximum huge page size 28 // that the runtime supports. 29 maxPhysHugePageSize = pallocChunkBytes 30 31 // pagesPerReclaimerChunk indicates how many pages to scan from the 32 // pageInUse bitmap at a time. Used by the page reclaimer. 33 // 34 // Higher values reduce contention on scanning indexes (such as 35 // h.reclaimIndex), but increase the minimum latency of the 36 // operation. 37 // 38 // The time required to scan this many pages can vary a lot depending 39 // on how many spans are actually freed. Experimentally, it can 40 // scan for pages at ~300 GB/ms on a 2.6GHz Core i7, but can only 41 // free spans at ~32 MB/ms. Using 512 pages bounds this at 42 // roughly 100µs. 43 // 44 // Must be a multiple of the pageInUse bitmap element size and 45 // must also evenly divide pagesPerArena. 46 pagesPerReclaimerChunk = 512 47 48 // physPageAlignedStacks indicates whether stack allocations must be 49 // physical page aligned. This is a requirement for MAP_STACK on 50 // OpenBSD. 51 physPageAlignedStacks = GOOS == "openbsd" 52) 53 54// Main malloc heap. 55// The heap itself is the "free" and "scav" treaps, 56// but all the other global data is here too. 57// 58// mheap must not be heap-allocated because it contains mSpanLists, 59// which must not be heap-allocated. 60// 61//go:notinheap 62type mheap struct { 63 // lock must only be acquired on the system stack, otherwise a g 64 // could self-deadlock if its stack grows with the lock held. 65 lock mutex 66 pages pageAlloc // page allocation data structure 67 sweepgen uint32 // sweep generation, see comment in mspan; written during STW 68 sweepdone uint32 // all spans are swept 69 sweepers uint32 // number of active sweepone calls 70 71 // allspans is a slice of all mspans ever created. Each mspan 72 // appears exactly once. 73 // 74 // The memory for allspans is manually managed and can be 75 // reallocated and move as the heap grows. 76 // 77 // In general, allspans is protected by mheap_.lock, which 78 // prevents concurrent access as well as freeing the backing 79 // store. Accesses during STW might not hold the lock, but 80 // must ensure that allocation cannot happen around the 81 // access (since that may free the backing store). 82 allspans []*mspan // all spans out there 83 84 _ uint32 // align uint64 fields on 32-bit for atomics 85 86 // Proportional sweep 87 // 88 // These parameters represent a linear function from heap_live 89 // to page sweep count. The proportional sweep system works to 90 // stay in the black by keeping the current page sweep count 91 // above this line at the current heap_live. 92 // 93 // The line has slope sweepPagesPerByte and passes through a 94 // basis point at (sweepHeapLiveBasis, pagesSweptBasis). At 95 // any given time, the system is at (memstats.heap_live, 96 // pagesSwept) in this space. 97 // 98 // It's important that the line pass through a point we 99 // control rather than simply starting at a (0,0) origin 100 // because that lets us adjust sweep pacing at any time while 101 // accounting for current progress. If we could only adjust 102 // the slope, it would create a discontinuity in debt if any 103 // progress has already been made. 104 pagesInUse uint64 // pages of spans in stats mSpanInUse; updated atomically 105 pagesSwept uint64 // pages swept this cycle; updated atomically 106 pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically 107 sweepHeapLiveBasis uint64 // value of heap_live to use as the origin of sweep ratio; written with lock, read without 108 sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without 109 // TODO(austin): pagesInUse should be a uintptr, but the 386 110 // compiler can't 8-byte align fields. 111 112 // scavengeGoal is the amount of total retained heap memory (measured by 113 // heapRetained) that the runtime will try to maintain by returning memory 114 // to the OS. 115 scavengeGoal uint64 116 117 // Page reclaimer state 118 119 // reclaimIndex is the page index in allArenas of next page to 120 // reclaim. Specifically, it refers to page (i % 121 // pagesPerArena) of arena allArenas[i / pagesPerArena]. 122 // 123 // If this is >= 1<<63, the page reclaimer is done scanning 124 // the page marks. 125 // 126 // This is accessed atomically. 127 reclaimIndex uint64 128 // reclaimCredit is spare credit for extra pages swept. Since 129 // the page reclaimer works in large chunks, it may reclaim 130 // more than requested. Any spare pages released go to this 131 // credit pool. 132 // 133 // This is accessed atomically. 134 reclaimCredit uintptr 135 136 // arenas is the heap arena map. It points to the metadata for 137 // the heap for every arena frame of the entire usable virtual 138 // address space. 139 // 140 // Use arenaIndex to compute indexes into this array. 141 // 142 // For regions of the address space that are not backed by the 143 // Go heap, the arena map contains nil. 144 // 145 // Modifications are protected by mheap_.lock. Reads can be 146 // performed without locking; however, a given entry can 147 // transition from nil to non-nil at any time when the lock 148 // isn't held. (Entries never transitions back to nil.) 149 // 150 // In general, this is a two-level mapping consisting of an L1 151 // map and possibly many L2 maps. This saves space when there 152 // are a huge number of arena frames. However, on many 153 // platforms (even 64-bit), arenaL1Bits is 0, making this 154 // effectively a single-level map. In this case, arenas[0] 155 // will never be nil. 156 arenas [1 << arenaL1Bits]*[1 << arenaL2Bits]*heapArena 157 158 // heapArenaAlloc is pre-reserved space for allocating heapArena 159 // objects. This is only used on 32-bit, where we pre-reserve 160 // this space to avoid interleaving it with the heap itself. 161 heapArenaAlloc linearAlloc 162 163 // arenaHints is a list of addresses at which to attempt to 164 // add more heap arenas. This is initially populated with a 165 // set of general hint addresses, and grown with the bounds of 166 // actual heap arena ranges. 167 arenaHints *arenaHint 168 169 // arena is a pre-reserved space for allocating heap arenas 170 // (the actual arenas). This is only used on 32-bit. 171 arena linearAlloc 172 173 // allArenas is the arenaIndex of every mapped arena. This can 174 // be used to iterate through the address space. 175 // 176 // Access is protected by mheap_.lock. However, since this is 177 // append-only and old backing arrays are never freed, it is 178 // safe to acquire mheap_.lock, copy the slice header, and 179 // then release mheap_.lock. 180 allArenas []arenaIdx 181 182 // sweepArenas is a snapshot of allArenas taken at the 183 // beginning of the sweep cycle. This can be read safely by 184 // simply blocking GC (by disabling preemption). 185 sweepArenas []arenaIdx 186 187 // markArenas is a snapshot of allArenas taken at the beginning 188 // of the mark cycle. Because allArenas is append-only, neither 189 // this slice nor its contents will change during the mark, so 190 // it can be read safely. 191 markArenas []arenaIdx 192 193 // curArena is the arena that the heap is currently growing 194 // into. This should always be physPageSize-aligned. 195 curArena struct { 196 base, end uintptr 197 } 198 199 _ uint32 // ensure 64-bit alignment of central 200 201 // central free lists for small size classes. 202 // the padding makes sure that the mcentrals are 203 // spaced CacheLinePadSize bytes apart, so that each mcentral.lock 204 // gets its own cache line. 205 // central is indexed by spanClass. 206 central [numSpanClasses]struct { 207 mcentral mcentral 208 pad [cpu.CacheLinePadSize - unsafe.Sizeof(mcentral{})%cpu.CacheLinePadSize]byte 209 } 210 211 spanalloc fixalloc // allocator for span* 212 cachealloc fixalloc // allocator for mcache* 213 specialfinalizeralloc fixalloc // allocator for specialfinalizer* 214 specialprofilealloc fixalloc // allocator for specialprofile* 215 speciallock mutex // lock for special record allocators. 216 arenaHintAlloc fixalloc // allocator for arenaHints 217 218 unused *specialfinalizer // never set, just here to force the specialfinalizer type into DWARF 219} 220 221var mheap_ mheap 222 223// A heapArena stores metadata for a heap arena. heapArenas are stored 224// outside of the Go heap and accessed via the mheap_.arenas index. 225// 226//go:notinheap 227type heapArena struct { 228 // bitmap stores the pointer/scalar bitmap for the words in 229 // this arena. See mbitmap.go for a description. Use the 230 // heapBits type to access this. 231 bitmap [heapArenaBitmapBytes]byte 232 233 // spans maps from virtual address page ID within this arena to *mspan. 234 // For allocated spans, their pages map to the span itself. 235 // For free spans, only the lowest and highest pages map to the span itself. 236 // Internal pages map to an arbitrary span. 237 // For pages that have never been allocated, spans entries are nil. 238 // 239 // Modifications are protected by mheap.lock. Reads can be 240 // performed without locking, but ONLY from indexes that are 241 // known to contain in-use or stack spans. This means there 242 // must not be a safe-point between establishing that an 243 // address is live and looking it up in the spans array. 244 spans [pagesPerArena]*mspan 245 246 // pageInUse is a bitmap that indicates which spans are in 247 // state mSpanInUse. This bitmap is indexed by page number, 248 // but only the bit corresponding to the first page in each 249 // span is used. 250 // 251 // Reads and writes are atomic. 252 pageInUse [pagesPerArena / 8]uint8 253 254 // pageMarks is a bitmap that indicates which spans have any 255 // marked objects on them. Like pageInUse, only the bit 256 // corresponding to the first page in each span is used. 257 // 258 // Writes are done atomically during marking. Reads are 259 // non-atomic and lock-free since they only occur during 260 // sweeping (and hence never race with writes). 261 // 262 // This is used to quickly find whole spans that can be freed. 263 // 264 // TODO(austin): It would be nice if this was uint64 for 265 // faster scanning, but we don't have 64-bit atomic bit 266 // operations. 267 pageMarks [pagesPerArena / 8]uint8 268 269 // pageSpecials is a bitmap that indicates which spans have 270 // specials (finalizers or other). Like pageInUse, only the bit 271 // corresponding to the first page in each span is used. 272 // 273 // Writes are done atomically whenever a special is added to 274 // a span and whenever the last special is removed from a span. 275 // Reads are done atomically to find spans containing specials 276 // during marking. 277 pageSpecials [pagesPerArena / 8]uint8 278 279 // checkmarks stores the debug.gccheckmark state. It is only 280 // used if debug.gccheckmark > 0. 281 checkmarks *checkmarksMap 282 283 // zeroedBase marks the first byte of the first page in this 284 // arena which hasn't been used yet and is therefore already 285 // zero. zeroedBase is relative to the arena base. 286 // Increases monotonically until it hits heapArenaBytes. 287 // 288 // This field is sufficient to determine if an allocation 289 // needs to be zeroed because the page allocator follows an 290 // address-ordered first-fit policy. 291 // 292 // Read atomically and written with an atomic CAS. 293 zeroedBase uintptr 294} 295 296// arenaHint is a hint for where to grow the heap arenas. See 297// mheap_.arenaHints. 298// 299//go:notinheap 300type arenaHint struct { 301 addr uintptr 302 down bool 303 next *arenaHint 304} 305 306// An mspan is a run of pages. 307// 308// When a mspan is in the heap free treap, state == mSpanFree 309// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span. 310// If the mspan is in the heap scav treap, then in addition to the 311// above scavenged == true. scavenged == false in all other cases. 312// 313// When a mspan is allocated, state == mSpanInUse or mSpanManual 314// and heapmap(i) == span for all s->start <= i < s->start+s->npages. 315 316// Every mspan is in one doubly-linked list, either in the mheap's 317// busy list or one of the mcentral's span lists. 318 319// An mspan representing actual memory has state mSpanInUse, 320// mSpanManual, or mSpanFree. Transitions between these states are 321// constrained as follows: 322// 323// * A span may transition from free to in-use or manual during any GC 324// phase. 325// 326// * During sweeping (gcphase == _GCoff), a span may transition from 327// in-use to free (as a result of sweeping) or manual to free (as a 328// result of stacks being freed). 329// 330// * During GC (gcphase != _GCoff), a span *must not* transition from 331// manual or in-use to free. Because concurrent GC may read a pointer 332// and then look up its span, the span state must be monotonic. 333// 334// Setting mspan.state to mSpanInUse or mSpanManual must be done 335// atomically and only after all other span fields are valid. 336// Likewise, if inspecting a span is contingent on it being 337// mSpanInUse, the state should be loaded atomically and checked 338// before depending on other fields. This allows the garbage collector 339// to safely deal with potentially invalid pointers, since resolving 340// such pointers may race with a span being allocated. 341type mSpanState uint8 342 343const ( 344 mSpanDead mSpanState = iota 345 mSpanInUse // allocated for garbage collected heap 346 mSpanManual // allocated for manual management (e.g., stack allocator) 347) 348 349// mSpanStateNames are the names of the span states, indexed by 350// mSpanState. 351var mSpanStateNames = []string{ 352 "mSpanDead", 353 "mSpanInUse", 354 "mSpanManual", 355 "mSpanFree", 356} 357 358// mSpanStateBox holds an mSpanState and provides atomic operations on 359// it. This is a separate type to disallow accidental comparison or 360// assignment with mSpanState. 361type mSpanStateBox struct { 362 s mSpanState 363} 364 365func (b *mSpanStateBox) set(s mSpanState) { 366 atomic.Store8((*uint8)(&b.s), uint8(s)) 367} 368 369func (b *mSpanStateBox) get() mSpanState { 370 return mSpanState(atomic.Load8((*uint8)(&b.s))) 371} 372 373// mSpanList heads a linked list of spans. 374// 375//go:notinheap 376type mSpanList struct { 377 first *mspan // first span in list, or nil if none 378 last *mspan // last span in list, or nil if none 379} 380 381//go:notinheap 382type mspan struct { 383 next *mspan // next span in list, or nil if none 384 prev *mspan // previous span in list, or nil if none 385 list *mSpanList // For debugging. TODO: Remove. 386 387 startAddr uintptr // address of first byte of span aka s.base() 388 npages uintptr // number of pages in span 389 390 manualFreeList gclinkptr // list of free objects in mSpanManual spans 391 392 // freeindex is the slot index between 0 and nelems at which to begin scanning 393 // for the next free object in this span. 394 // Each allocation scans allocBits starting at freeindex until it encounters a 0 395 // indicating a free object. freeindex is then adjusted so that subsequent scans begin 396 // just past the newly discovered free object. 397 // 398 // If freeindex == nelem, this span has no free objects. 399 // 400 // allocBits is a bitmap of objects in this span. 401 // If n >= freeindex and allocBits[n/8] & (1<<(n%8)) is 0 402 // then object n is free; 403 // otherwise, object n is allocated. Bits starting at nelem are 404 // undefined and should never be referenced. 405 // 406 // Object n starts at address n*elemsize + (start << pageShift). 407 freeindex uintptr 408 // TODO: Look up nelems from sizeclass and remove this field if it 409 // helps performance. 410 nelems uintptr // number of object in the span. 411 412 // Cache of the allocBits at freeindex. allocCache is shifted 413 // such that the lowest bit corresponds to the bit freeindex. 414 // allocCache holds the complement of allocBits, thus allowing 415 // ctz (count trailing zero) to use it directly. 416 // allocCache may contain bits beyond s.nelems; the caller must ignore 417 // these. 418 allocCache uint64 419 420 // allocBits and gcmarkBits hold pointers to a span's mark and 421 // allocation bits. The pointers are 8 byte aligned. 422 // There are three arenas where this data is held. 423 // free: Dirty arenas that are no longer accessed 424 // and can be reused. 425 // next: Holds information to be used in the next GC cycle. 426 // current: Information being used during this GC cycle. 427 // previous: Information being used during the last GC cycle. 428 // A new GC cycle starts with the call to finishsweep_m. 429 // finishsweep_m moves the previous arena to the free arena, 430 // the current arena to the previous arena, and 431 // the next arena to the current arena. 432 // The next arena is populated as the spans request 433 // memory to hold gcmarkBits for the next GC cycle as well 434 // as allocBits for newly allocated spans. 435 // 436 // The pointer arithmetic is done "by hand" instead of using 437 // arrays to avoid bounds checks along critical performance 438 // paths. 439 // The sweep will free the old allocBits and set allocBits to the 440 // gcmarkBits. The gcmarkBits are replaced with a fresh zeroed 441 // out memory. 442 allocBits *gcBits 443 gcmarkBits *gcBits 444 445 // sweep generation: 446 // if sweepgen == h->sweepgen - 2, the span needs sweeping 447 // if sweepgen == h->sweepgen - 1, the span is currently being swept 448 // if sweepgen == h->sweepgen, the span is swept and ready to use 449 // if sweepgen == h->sweepgen + 1, the span was cached before sweep began and is still cached, and needs sweeping 450 // if sweepgen == h->sweepgen + 3, the span was swept and then cached and is still cached 451 // h->sweepgen is incremented by 2 after every GC 452 453 sweepgen uint32 454 divMul uint16 // for divide by elemsize - divMagic.mul 455 baseMask uint16 // if non-0, elemsize is a power of 2, & this will get object allocation base 456 allocCount uint16 // number of allocated objects 457 spanclass spanClass // size class and noscan (uint8) 458 state mSpanStateBox // mSpanInUse etc; accessed atomically (get/set methods) 459 needzero uint8 // needs to be zeroed before allocation 460 divShift uint8 // for divide by elemsize - divMagic.shift 461 divShift2 uint8 // for divide by elemsize - divMagic.shift2 462 elemsize uintptr // computed from sizeclass or from npages 463 limit uintptr // end of data in span 464 speciallock mutex // guards specials list 465 specials *special // linked list of special records sorted by offset. 466} 467 468func (s *mspan) base() uintptr { 469 return s.startAddr 470} 471 472func (s *mspan) layout() (size, n, total uintptr) { 473 total = s.npages << _PageShift 474 size = s.elemsize 475 if size > 0 { 476 n = total / size 477 } 478 return 479} 480 481// recordspan adds a newly allocated span to h.allspans. 482// 483// This only happens the first time a span is allocated from 484// mheap.spanalloc (it is not called when a span is reused). 485// 486// Write barriers are disallowed here because it can be called from 487// gcWork when allocating new workbufs. However, because it's an 488// indirect call from the fixalloc initializer, the compiler can't see 489// this. 490// 491// The heap lock must be held. 492// 493//go:nowritebarrierrec 494func recordspan(vh unsafe.Pointer, p unsafe.Pointer) { 495 h := (*mheap)(vh) 496 s := (*mspan)(p) 497 498 assertLockHeld(&h.lock) 499 500 if len(h.allspans) >= cap(h.allspans) { 501 n := 64 * 1024 / sys.PtrSize 502 if n < cap(h.allspans)*3/2 { 503 n = cap(h.allspans) * 3 / 2 504 } 505 var new []*mspan 506 sp := (*notInHeapSlice)(unsafe.Pointer(&new)) 507 sp.array = (*notInHeap)(sysAlloc(uintptr(n)*sys.PtrSize, &memstats.other_sys)) 508 if sp.array == nil { 509 throw("runtime: cannot allocate memory") 510 } 511 sp.len = len(h.allspans) 512 sp.cap = n 513 if len(h.allspans) > 0 { 514 copy(new, h.allspans) 515 } 516 oldAllspans := h.allspans 517 *(*notInHeapSlice)(unsafe.Pointer(&h.allspans)) = *(*notInHeapSlice)(unsafe.Pointer(&new)) 518 if len(oldAllspans) != 0 { 519 sysFree(unsafe.Pointer(&oldAllspans[0]), uintptr(cap(oldAllspans))*unsafe.Sizeof(oldAllspans[0]), &memstats.other_sys) 520 } 521 } 522 h.allspans = h.allspans[:len(h.allspans)+1] 523 h.allspans[len(h.allspans)-1] = s 524} 525 526// A spanClass represents the size class and noscan-ness of a span. 527// 528// Each size class has a noscan spanClass and a scan spanClass. The 529// noscan spanClass contains only noscan objects, which do not contain 530// pointers and thus do not need to be scanned by the garbage 531// collector. 532type spanClass uint8 533 534const ( 535 numSpanClasses = _NumSizeClasses << 1 536 tinySpanClass = spanClass(tinySizeClass<<1 | 1) 537) 538 539func makeSpanClass(sizeclass uint8, noscan bool) spanClass { 540 return spanClass(sizeclass<<1) | spanClass(bool2int(noscan)) 541} 542 543func (sc spanClass) sizeclass() int8 { 544 return int8(sc >> 1) 545} 546 547func (sc spanClass) noscan() bool { 548 return sc&1 != 0 549} 550 551// arenaIndex returns the index into mheap_.arenas of the arena 552// containing metadata for p. This index combines of an index into the 553// L1 map and an index into the L2 map and should be used as 554// mheap_.arenas[ai.l1()][ai.l2()]. 555// 556// If p is outside the range of valid heap addresses, either l1() or 557// l2() will be out of bounds. 558// 559// It is nosplit because it's called by spanOf and several other 560// nosplit functions. 561// 562//go:nosplit 563func arenaIndex(p uintptr) arenaIdx { 564 return arenaIdx((p - arenaBaseOffset) / heapArenaBytes) 565} 566 567// arenaBase returns the low address of the region covered by heap 568// arena i. 569func arenaBase(i arenaIdx) uintptr { 570 return uintptr(i)*heapArenaBytes + arenaBaseOffset 571} 572 573type arenaIdx uint 574 575func (i arenaIdx) l1() uint { 576 if arenaL1Bits == 0 { 577 // Let the compiler optimize this away if there's no 578 // L1 map. 579 return 0 580 } else { 581 return uint(i) >> arenaL1Shift 582 } 583} 584 585func (i arenaIdx) l2() uint { 586 if arenaL1Bits == 0 { 587 return uint(i) 588 } else { 589 return uint(i) & (1<<arenaL2Bits - 1) 590 } 591} 592 593// inheap reports whether b is a pointer into a (potentially dead) heap object. 594// It returns false for pointers into mSpanManual spans. 595// Non-preemptible because it is used by write barriers. 596//go:nowritebarrier 597//go:nosplit 598func inheap(b uintptr) bool { 599 return spanOfHeap(b) != nil 600} 601 602// inHeapOrStack is a variant of inheap that returns true for pointers 603// into any allocated heap span. 604// 605//go:nowritebarrier 606//go:nosplit 607func inHeapOrStack(b uintptr) bool { 608 s := spanOf(b) 609 if s == nil || b < s.base() { 610 return false 611 } 612 switch s.state.get() { 613 case mSpanInUse, mSpanManual: 614 return b < s.limit 615 default: 616 return false 617 } 618} 619 620// spanOf returns the span of p. If p does not point into the heap 621// arena or no span has ever contained p, spanOf returns nil. 622// 623// If p does not point to allocated memory, this may return a non-nil 624// span that does *not* contain p. If this is a possibility, the 625// caller should either call spanOfHeap or check the span bounds 626// explicitly. 627// 628// Must be nosplit because it has callers that are nosplit. 629// 630//go:nosplit 631func spanOf(p uintptr) *mspan { 632 // This function looks big, but we use a lot of constant 633 // folding around arenaL1Bits to get it under the inlining 634 // budget. Also, many of the checks here are safety checks 635 // that Go needs to do anyway, so the generated code is quite 636 // short. 637 ri := arenaIndex(p) 638 if arenaL1Bits == 0 { 639 // If there's no L1, then ri.l1() can't be out of bounds but ri.l2() can. 640 if ri.l2() >= uint(len(mheap_.arenas[0])) { 641 return nil 642 } 643 } else { 644 // If there's an L1, then ri.l1() can be out of bounds but ri.l2() can't. 645 if ri.l1() >= uint(len(mheap_.arenas)) { 646 return nil 647 } 648 } 649 l2 := mheap_.arenas[ri.l1()] 650 if arenaL1Bits != 0 && l2 == nil { // Should never happen if there's no L1. 651 return nil 652 } 653 ha := l2[ri.l2()] 654 if ha == nil { 655 return nil 656 } 657 return ha.spans[(p/pageSize)%pagesPerArena] 658} 659 660// spanOfUnchecked is equivalent to spanOf, but the caller must ensure 661// that p points into an allocated heap arena. 662// 663// Must be nosplit because it has callers that are nosplit. 664// 665//go:nosplit 666func spanOfUnchecked(p uintptr) *mspan { 667 ai := arenaIndex(p) 668 return mheap_.arenas[ai.l1()][ai.l2()].spans[(p/pageSize)%pagesPerArena] 669} 670 671// spanOfHeap is like spanOf, but returns nil if p does not point to a 672// heap object. 673// 674// Must be nosplit because it has callers that are nosplit. 675// 676//go:nosplit 677func spanOfHeap(p uintptr) *mspan { 678 s := spanOf(p) 679 // s is nil if it's never been allocated. Otherwise, we check 680 // its state first because we don't trust this pointer, so we 681 // have to synchronize with span initialization. Then, it's 682 // still possible we picked up a stale span pointer, so we 683 // have to check the span's bounds. 684 if s == nil || s.state.get() != mSpanInUse || p < s.base() || p >= s.limit { 685 return nil 686 } 687 return s 688} 689 690// pageIndexOf returns the arena, page index, and page mask for pointer p. 691// The caller must ensure p is in the heap. 692func pageIndexOf(p uintptr) (arena *heapArena, pageIdx uintptr, pageMask uint8) { 693 ai := arenaIndex(p) 694 arena = mheap_.arenas[ai.l1()][ai.l2()] 695 pageIdx = ((p / pageSize) / 8) % uintptr(len(arena.pageInUse)) 696 pageMask = byte(1 << ((p / pageSize) % 8)) 697 return 698} 699 700// Initialize the heap. 701func (h *mheap) init() { 702 lockInit(&h.lock, lockRankMheap) 703 lockInit(&h.speciallock, lockRankMheapSpecial) 704 705 h.spanalloc.init(unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys) 706 h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys) 707 h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys) 708 h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys) 709 h.arenaHintAlloc.init(unsafe.Sizeof(arenaHint{}), nil, nil, &memstats.other_sys) 710 711 // Don't zero mspan allocations. Background sweeping can 712 // inspect a span concurrently with allocating it, so it's 713 // important that the span's sweepgen survive across freeing 714 // and re-allocating a span to prevent background sweeping 715 // from improperly cas'ing it from 0. 716 // 717 // This is safe because mspan contains no heap pointers. 718 h.spanalloc.zero = false 719 720 // h->mapcache needs no init 721 722 for i := range h.central { 723 h.central[i].mcentral.init(spanClass(i)) 724 } 725 726 h.pages.init(&h.lock, &memstats.gcMiscSys) 727} 728 729// reclaim sweeps and reclaims at least npage pages into the heap. 730// It is called before allocating npage pages to keep growth in check. 731// 732// reclaim implements the page-reclaimer half of the sweeper. 733// 734// h.lock must NOT be held. 735func (h *mheap) reclaim(npage uintptr) { 736 // TODO(austin): Half of the time spent freeing spans is in 737 // locking/unlocking the heap (even with low contention). We 738 // could make the slow path here several times faster by 739 // batching heap frees. 740 741 // Bail early if there's no more reclaim work. 742 if atomic.Load64(&h.reclaimIndex) >= 1<<63 { 743 return 744 } 745 746 // Disable preemption so the GC can't start while we're 747 // sweeping, so we can read h.sweepArenas, and so 748 // traceGCSweepStart/Done pair on the P. 749 mp := acquirem() 750 751 if trace.enabled { 752 traceGCSweepStart() 753 } 754 755 arenas := h.sweepArenas 756 locked := false 757 for npage > 0 { 758 // Pull from accumulated credit first. 759 if credit := atomic.Loaduintptr(&h.reclaimCredit); credit > 0 { 760 take := credit 761 if take > npage { 762 // Take only what we need. 763 take = npage 764 } 765 if atomic.Casuintptr(&h.reclaimCredit, credit, credit-take) { 766 npage -= take 767 } 768 continue 769 } 770 771 // Claim a chunk of work. 772 idx := uintptr(atomic.Xadd64(&h.reclaimIndex, pagesPerReclaimerChunk) - pagesPerReclaimerChunk) 773 if idx/pagesPerArena >= uintptr(len(arenas)) { 774 // Page reclaiming is done. 775 atomic.Store64(&h.reclaimIndex, 1<<63) 776 break 777 } 778 779 if !locked { 780 // Lock the heap for reclaimChunk. 781 lock(&h.lock) 782 locked = true 783 } 784 785 // Scan this chunk. 786 nfound := h.reclaimChunk(arenas, idx, pagesPerReclaimerChunk) 787 if nfound <= npage { 788 npage -= nfound 789 } else { 790 // Put spare pages toward global credit. 791 atomic.Xadduintptr(&h.reclaimCredit, nfound-npage) 792 npage = 0 793 } 794 } 795 if locked { 796 unlock(&h.lock) 797 } 798 799 if trace.enabled { 800 traceGCSweepDone() 801 } 802 releasem(mp) 803} 804 805// reclaimChunk sweeps unmarked spans that start at page indexes [pageIdx, pageIdx+n). 806// It returns the number of pages returned to the heap. 807// 808// h.lock must be held and the caller must be non-preemptible. Note: h.lock may be 809// temporarily unlocked and re-locked in order to do sweeping or if tracing is 810// enabled. 811func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { 812 // The heap lock must be held because this accesses the 813 // heapArena.spans arrays using potentially non-live pointers. 814 // In particular, if a span were freed and merged concurrently 815 // with this probing heapArena.spans, it would be possible to 816 // observe arbitrary, stale span pointers. 817 assertLockHeld(&h.lock) 818 819 n0 := n 820 var nFreed uintptr 821 sg := h.sweepgen 822 for n > 0 { 823 ai := arenas[pageIdx/pagesPerArena] 824 ha := h.arenas[ai.l1()][ai.l2()] 825 826 // Get a chunk of the bitmap to work on. 827 arenaPage := uint(pageIdx % pagesPerArena) 828 inUse := ha.pageInUse[arenaPage/8:] 829 marked := ha.pageMarks[arenaPage/8:] 830 if uintptr(len(inUse)) > n/8 { 831 inUse = inUse[:n/8] 832 marked = marked[:n/8] 833 } 834 835 // Scan this bitmap chunk for spans that are in-use 836 // but have no marked objects on them. 837 for i := range inUse { 838 inUseUnmarked := atomic.Load8(&inUse[i]) &^ marked[i] 839 if inUseUnmarked == 0 { 840 continue 841 } 842 843 for j := uint(0); j < 8; j++ { 844 if inUseUnmarked&(1<<j) != 0 { 845 s := ha.spans[arenaPage+uint(i)*8+j] 846 if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { 847 npages := s.npages 848 unlock(&h.lock) 849 if s.sweep(false) { 850 nFreed += npages 851 } 852 lock(&h.lock) 853 // Reload inUse. It's possible nearby 854 // spans were freed when we dropped the 855 // lock and we don't want to get stale 856 // pointers from the spans array. 857 inUseUnmarked = atomic.Load8(&inUse[i]) &^ marked[i] 858 } 859 } 860 } 861 } 862 863 // Advance. 864 pageIdx += uintptr(len(inUse) * 8) 865 n -= uintptr(len(inUse) * 8) 866 } 867 if trace.enabled { 868 unlock(&h.lock) 869 // Account for pages scanned but not reclaimed. 870 traceGCSweepSpan((n0 - nFreed) * pageSize) 871 lock(&h.lock) 872 } 873 874 assertLockHeld(&h.lock) // Must be locked on return. 875 return nFreed 876} 877 878// spanAllocType represents the type of allocation to make, or 879// the type of allocation to be freed. 880type spanAllocType uint8 881 882const ( 883 spanAllocHeap spanAllocType = iota // heap span 884 spanAllocStack // stack span 885 spanAllocPtrScalarBits // unrolled GC prog bitmap span 886 spanAllocWorkBuf // work buf span 887) 888 889// manual returns true if the span allocation is manually managed. 890func (s spanAllocType) manual() bool { 891 return s != spanAllocHeap 892} 893 894// alloc allocates a new span of npage pages from the GC'd heap. 895// 896// spanclass indicates the span's size class and scannability. 897// 898// If needzero is true, the memory for the returned span will be zeroed. 899func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) *mspan { 900 // Don't do any operations that lock the heap on the G stack. 901 // It might trigger stack growth, and the stack growth code needs 902 // to be able to allocate heap. 903 var s *mspan 904 systemstack(func() { 905 // To prevent excessive heap growth, before allocating n pages 906 // we need to sweep and reclaim at least n pages. 907 if h.sweepdone == 0 { 908 h.reclaim(npages) 909 } 910 s = h.allocSpan(npages, spanAllocHeap, spanclass) 911 }) 912 913 if s != nil { 914 if needzero && s.needzero != 0 { 915 memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift) 916 } 917 s.needzero = 0 918 } 919 return s 920} 921 922// allocManual allocates a manually-managed span of npage pages. 923// allocManual returns nil if allocation fails. 924// 925// allocManual adds the bytes used to *stat, which should be a 926// memstats in-use field. Unlike allocations in the GC'd heap, the 927// allocation does *not* count toward heap_inuse or heap_sys. 928// 929// The memory backing the returned span may not be zeroed if 930// span.needzero is set. 931// 932// allocManual must be called on the system stack because it may 933// acquire the heap lock via allocSpan. See mheap for details. 934// 935// If new code is written to call allocManual, do NOT use an 936// existing spanAllocType value and instead declare a new one. 937// 938//go:systemstack 939func (h *mheap) allocManual(npages uintptr, typ spanAllocType) *mspan { 940 if !typ.manual() { 941 throw("manual span allocation called with non-manually-managed type") 942 } 943 return h.allocSpan(npages, typ, 0) 944} 945 946// setSpans modifies the span map so [spanOf(base), spanOf(base+npage*pageSize)) 947// is s. 948func (h *mheap) setSpans(base, npage uintptr, s *mspan) { 949 p := base / pageSize 950 ai := arenaIndex(base) 951 ha := h.arenas[ai.l1()][ai.l2()] 952 for n := uintptr(0); n < npage; n++ { 953 i := (p + n) % pagesPerArena 954 if i == 0 { 955 ai = arenaIndex(base + n*pageSize) 956 ha = h.arenas[ai.l1()][ai.l2()] 957 } 958 ha.spans[i] = s 959 } 960} 961 962// allocNeedsZero checks if the region of address space [base, base+npage*pageSize), 963// assumed to be allocated, needs to be zeroed, updating heap arena metadata for 964// future allocations. 965// 966// This must be called each time pages are allocated from the heap, even if the page 967// allocator can otherwise prove the memory it's allocating is already zero because 968// they're fresh from the operating system. It updates heapArena metadata that is 969// critical for future page allocations. 970// 971// There are no locking constraints on this method. 972func (h *mheap) allocNeedsZero(base, npage uintptr) (needZero bool) { 973 for npage > 0 { 974 ai := arenaIndex(base) 975 ha := h.arenas[ai.l1()][ai.l2()] 976 977 zeroedBase := atomic.Loaduintptr(&ha.zeroedBase) 978 arenaBase := base % heapArenaBytes 979 if arenaBase < zeroedBase { 980 // We extended into the non-zeroed part of the 981 // arena, so this region needs to be zeroed before use. 982 // 983 // zeroedBase is monotonically increasing, so if we see this now then 984 // we can be sure we need to zero this memory region. 985 // 986 // We still need to update zeroedBase for this arena, and 987 // potentially more arenas. 988 needZero = true 989 } 990 // We may observe arenaBase > zeroedBase if we're racing with one or more 991 // allocations which are acquiring memory directly before us in the address 992 // space. But, because we know no one else is acquiring *this* memory, it's 993 // still safe to not zero. 994 995 // Compute how far into the arena we extend into, capped 996 // at heapArenaBytes. 997 arenaLimit := arenaBase + npage*pageSize 998 if arenaLimit > heapArenaBytes { 999 arenaLimit = heapArenaBytes 1000 } 1001 // Increase ha.zeroedBase so it's >= arenaLimit. 1002 // We may be racing with other updates. 1003 for arenaLimit > zeroedBase { 1004 if atomic.Casuintptr(&ha.zeroedBase, zeroedBase, arenaLimit) { 1005 break 1006 } 1007 zeroedBase = atomic.Loaduintptr(&ha.zeroedBase) 1008 // Sanity check zeroedBase. 1009 if zeroedBase <= arenaLimit && zeroedBase > arenaBase { 1010 // The zeroedBase moved into the space we were trying to 1011 // claim. That's very bad, and indicates someone allocated 1012 // the same region we did. 1013 throw("potentially overlapping in-use allocations detected") 1014 } 1015 } 1016 1017 // Move base forward and subtract from npage to move into 1018 // the next arena, or finish. 1019 base += arenaLimit - arenaBase 1020 npage -= (arenaLimit - arenaBase) / pageSize 1021 } 1022 return 1023} 1024 1025// tryAllocMSpan attempts to allocate an mspan object from 1026// the P-local cache, but may fail. 1027// 1028// h.lock need not be held. 1029// 1030// This caller must ensure that its P won't change underneath 1031// it during this function. Currently to ensure that we enforce 1032// that the function is run on the system stack, because that's 1033// the only place it is used now. In the future, this requirement 1034// may be relaxed if its use is necessary elsewhere. 1035// 1036//go:systemstack 1037func (h *mheap) tryAllocMSpan() *mspan { 1038 pp := getg().m.p.ptr() 1039 // If we don't have a p or the cache is empty, we can't do 1040 // anything here. 1041 if pp == nil || pp.mspancache.len == 0 { 1042 return nil 1043 } 1044 // Pull off the last entry in the cache. 1045 s := pp.mspancache.buf[pp.mspancache.len-1] 1046 pp.mspancache.len-- 1047 return s 1048} 1049 1050// allocMSpanLocked allocates an mspan object. 1051// 1052// h.lock must be held. 1053// 1054// allocMSpanLocked must be called on the system stack because 1055// its caller holds the heap lock. See mheap for details. 1056// Running on the system stack also ensures that we won't 1057// switch Ps during this function. See tryAllocMSpan for details. 1058// 1059//go:systemstack 1060func (h *mheap) allocMSpanLocked() *mspan { 1061 assertLockHeld(&h.lock) 1062 1063 pp := getg().m.p.ptr() 1064 if pp == nil { 1065 // We don't have a p so just do the normal thing. 1066 return (*mspan)(h.spanalloc.alloc()) 1067 } 1068 // Refill the cache if necessary. 1069 if pp.mspancache.len == 0 { 1070 const refillCount = len(pp.mspancache.buf) / 2 1071 for i := 0; i < refillCount; i++ { 1072 pp.mspancache.buf[i] = (*mspan)(h.spanalloc.alloc()) 1073 } 1074 pp.mspancache.len = refillCount 1075 } 1076 // Pull off the last entry in the cache. 1077 s := pp.mspancache.buf[pp.mspancache.len-1] 1078 pp.mspancache.len-- 1079 return s 1080} 1081 1082// freeMSpanLocked free an mspan object. 1083// 1084// h.lock must be held. 1085// 1086// freeMSpanLocked must be called on the system stack because 1087// its caller holds the heap lock. See mheap for details. 1088// Running on the system stack also ensures that we won't 1089// switch Ps during this function. See tryAllocMSpan for details. 1090// 1091//go:systemstack 1092func (h *mheap) freeMSpanLocked(s *mspan) { 1093 assertLockHeld(&h.lock) 1094 1095 pp := getg().m.p.ptr() 1096 // First try to free the mspan directly to the cache. 1097 if pp != nil && pp.mspancache.len < len(pp.mspancache.buf) { 1098 pp.mspancache.buf[pp.mspancache.len] = s 1099 pp.mspancache.len++ 1100 return 1101 } 1102 // Failing that (or if we don't have a p), just free it to 1103 // the heap. 1104 h.spanalloc.free(unsafe.Pointer(s)) 1105} 1106 1107// allocSpan allocates an mspan which owns npages worth of memory. 1108// 1109// If typ.manual() == false, allocSpan allocates a heap span of class spanclass 1110// and updates heap accounting. If manual == true, allocSpan allocates a 1111// manually-managed span (spanclass is ignored), and the caller is 1112// responsible for any accounting related to its use of the span. Either 1113// way, allocSpan will atomically add the bytes in the newly allocated 1114// span to *sysStat. 1115// 1116// The returned span is fully initialized. 1117// 1118// h.lock must not be held. 1119// 1120// allocSpan must be called on the system stack both because it acquires 1121// the heap lock and because it must block GC transitions. 1122// 1123//go:systemstack 1124func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass) (s *mspan) { 1125 // Function-global state. 1126 gp := getg() 1127 base, scav := uintptr(0), uintptr(0) 1128 1129 // On some platforms we need to provide physical page aligned stack 1130 // allocations. Where the page size is less than the physical page 1131 // size, we already manage to do this by default. 1132 needPhysPageAlign := physPageAlignedStacks && typ == spanAllocStack && pageSize < physPageSize 1133 1134 // If the allocation is small enough, try the page cache! 1135 // The page cache does not support aligned allocations, so we cannot use 1136 // it if we need to provide a physical page aligned stack allocation. 1137 pp := gp.m.p.ptr() 1138 if !needPhysPageAlign && pp != nil && npages < pageCachePages/4 { 1139 c := &pp.pcache 1140 1141 // If the cache is empty, refill it. 1142 if c.empty() { 1143 lock(&h.lock) 1144 *c = h.pages.allocToCache() 1145 unlock(&h.lock) 1146 } 1147 1148 // Try to allocate from the cache. 1149 base, scav = c.alloc(npages) 1150 if base != 0 { 1151 s = h.tryAllocMSpan() 1152 if s != nil { 1153 goto HaveSpan 1154 } 1155 // We have a base but no mspan, so we need 1156 // to lock the heap. 1157 } 1158 } 1159 1160 // For one reason or another, we couldn't get the 1161 // whole job done without the heap lock. 1162 lock(&h.lock) 1163 1164 if needPhysPageAlign { 1165 // Overallocate by a physical page to allow for later alignment. 1166 npages += physPageSize / pageSize 1167 } 1168 1169 if base == 0 { 1170 // Try to acquire a base address. 1171 base, scav = h.pages.alloc(npages) 1172 if base == 0 { 1173 if !h.grow(npages) { 1174 unlock(&h.lock) 1175 return nil 1176 } 1177 base, scav = h.pages.alloc(npages) 1178 if base == 0 { 1179 throw("grew heap, but no adequate free space found") 1180 } 1181 } 1182 } 1183 if s == nil { 1184 // We failed to get an mspan earlier, so grab 1185 // one now that we have the heap lock. 1186 s = h.allocMSpanLocked() 1187 } 1188 1189 if needPhysPageAlign { 1190 allocBase, allocPages := base, npages 1191 base = alignUp(allocBase, physPageSize) 1192 npages -= physPageSize / pageSize 1193 1194 // Return memory around the aligned allocation. 1195 spaceBefore := base - allocBase 1196 if spaceBefore > 0 { 1197 h.pages.free(allocBase, spaceBefore/pageSize) 1198 } 1199 spaceAfter := (allocPages-npages)*pageSize - spaceBefore 1200 if spaceAfter > 0 { 1201 h.pages.free(base+npages*pageSize, spaceAfter/pageSize) 1202 } 1203 } 1204 1205 unlock(&h.lock) 1206 1207HaveSpan: 1208 // At this point, both s != nil and base != 0, and the heap 1209 // lock is no longer held. Initialize the span. 1210 s.init(base, npages) 1211 if h.allocNeedsZero(base, npages) { 1212 s.needzero = 1 1213 } 1214 nbytes := npages * pageSize 1215 if typ.manual() { 1216 s.manualFreeList = 0 1217 s.nelems = 0 1218 s.limit = s.base() + s.npages*pageSize 1219 s.state.set(mSpanManual) 1220 } else { 1221 // We must set span properties before the span is published anywhere 1222 // since we're not holding the heap lock. 1223 s.spanclass = spanclass 1224 if sizeclass := spanclass.sizeclass(); sizeclass == 0 { 1225 s.elemsize = nbytes 1226 s.nelems = 1 1227 1228 s.divShift = 0 1229 s.divMul = 0 1230 s.divShift2 = 0 1231 s.baseMask = 0 1232 } else { 1233 s.elemsize = uintptr(class_to_size[sizeclass]) 1234 s.nelems = nbytes / s.elemsize 1235 1236 m := &class_to_divmagic[sizeclass] 1237 s.divShift = m.shift 1238 s.divMul = m.mul 1239 s.divShift2 = m.shift2 1240 s.baseMask = m.baseMask 1241 } 1242 1243 // Initialize mark and allocation structures. 1244 s.freeindex = 0 1245 s.allocCache = ^uint64(0) // all 1s indicating all free. 1246 s.gcmarkBits = newMarkBits(s.nelems) 1247 s.allocBits = newAllocBits(s.nelems) 1248 1249 // It's safe to access h.sweepgen without the heap lock because it's 1250 // only ever updated with the world stopped and we run on the 1251 // systemstack which blocks a STW transition. 1252 atomic.Store(&s.sweepgen, h.sweepgen) 1253 1254 // Now that the span is filled in, set its state. This 1255 // is a publication barrier for the other fields in 1256 // the span. While valid pointers into this span 1257 // should never be visible until the span is returned, 1258 // if the garbage collector finds an invalid pointer, 1259 // access to the span may race with initialization of 1260 // the span. We resolve this race by atomically 1261 // setting the state after the span is fully 1262 // initialized, and atomically checking the state in 1263 // any situation where a pointer is suspect. 1264 s.state.set(mSpanInUse) 1265 } 1266 1267 // Commit and account for any scavenged memory that the span now owns. 1268 if scav != 0 { 1269 // sysUsed all the pages that are actually available 1270 // in the span since some of them might be scavenged. 1271 sysUsed(unsafe.Pointer(base), nbytes) 1272 atomic.Xadd64(&memstats.heap_released, -int64(scav)) 1273 } 1274 // Update stats. 1275 if typ == spanAllocHeap { 1276 atomic.Xadd64(&memstats.heap_inuse, int64(nbytes)) 1277 } 1278 if typ.manual() { 1279 // Manually managed memory doesn't count toward heap_sys. 1280 memstats.heap_sys.add(-int64(nbytes)) 1281 } 1282 // Update consistent stats. 1283 stats := memstats.heapStats.acquire() 1284 atomic.Xaddint64(&stats.committed, int64(scav)) 1285 atomic.Xaddint64(&stats.released, -int64(scav)) 1286 switch typ { 1287 case spanAllocHeap: 1288 atomic.Xaddint64(&stats.inHeap, int64(nbytes)) 1289 case spanAllocStack: 1290 atomic.Xaddint64(&stats.inStacks, int64(nbytes)) 1291 case spanAllocPtrScalarBits: 1292 atomic.Xaddint64(&stats.inPtrScalarBits, int64(nbytes)) 1293 case spanAllocWorkBuf: 1294 atomic.Xaddint64(&stats.inWorkBufs, int64(nbytes)) 1295 } 1296 memstats.heapStats.release() 1297 1298 // Publish the span in various locations. 1299 1300 // This is safe to call without the lock held because the slots 1301 // related to this span will only ever be read or modified by 1302 // this thread until pointers into the span are published (and 1303 // we execute a publication barrier at the end of this function 1304 // before that happens) or pageInUse is updated. 1305 h.setSpans(s.base(), npages, s) 1306 1307 if !typ.manual() { 1308 // Mark in-use span in arena page bitmap. 1309 // 1310 // This publishes the span to the page sweeper, so 1311 // it's imperative that the span be completely initialized 1312 // prior to this line. 1313 arena, pageIdx, pageMask := pageIndexOf(s.base()) 1314 atomic.Or8(&arena.pageInUse[pageIdx], pageMask) 1315 1316 // Update related page sweeper stats. 1317 atomic.Xadd64(&h.pagesInUse, int64(npages)) 1318 } 1319 1320 // Make sure the newly allocated span will be observed 1321 // by the GC before pointers into the span are published. 1322 publicationBarrier() 1323 1324 return s 1325} 1326 1327// Try to add at least npage pages of memory to the heap, 1328// returning whether it worked. 1329// 1330// h.lock must be held. 1331func (h *mheap) grow(npage uintptr) bool { 1332 assertLockHeld(&h.lock) 1333 1334 // We must grow the heap in whole palloc chunks. 1335 ask := alignUp(npage, pallocChunkPages) * pageSize 1336 1337 totalGrowth := uintptr(0) 1338 // This may overflow because ask could be very large 1339 // and is otherwise unrelated to h.curArena.base. 1340 end := h.curArena.base + ask 1341 nBase := alignUp(end, physPageSize) 1342 if nBase > h.curArena.end || /* overflow */ end < h.curArena.base { 1343 // Not enough room in the current arena. Allocate more 1344 // arena space. This may not be contiguous with the 1345 // current arena, so we have to request the full ask. 1346 av, asize := h.sysAlloc(ask) 1347 if av == nil { 1348 print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n") 1349 return false 1350 } 1351 1352 if uintptr(av) == h.curArena.end { 1353 // The new space is contiguous with the old 1354 // space, so just extend the current space. 1355 h.curArena.end = uintptr(av) + asize 1356 } else { 1357 // The new space is discontiguous. Track what 1358 // remains of the current space and switch to 1359 // the new space. This should be rare. 1360 if size := h.curArena.end - h.curArena.base; size != 0 { 1361 h.pages.grow(h.curArena.base, size) 1362 totalGrowth += size 1363 } 1364 // Switch to the new space. 1365 h.curArena.base = uintptr(av) 1366 h.curArena.end = uintptr(av) + asize 1367 } 1368 1369 // The memory just allocated counts as both released 1370 // and idle, even though it's not yet backed by spans. 1371 // 1372 // The allocation is always aligned to the heap arena 1373 // size which is always > physPageSize, so its safe to 1374 // just add directly to heap_released. 1375 atomic.Xadd64(&memstats.heap_released, int64(asize)) 1376 stats := memstats.heapStats.acquire() 1377 atomic.Xaddint64(&stats.released, int64(asize)) 1378 memstats.heapStats.release() 1379 1380 // Recalculate nBase. 1381 // We know this won't overflow, because sysAlloc returned 1382 // a valid region starting at h.curArena.base which is at 1383 // least ask bytes in size. 1384 nBase = alignUp(h.curArena.base+ask, physPageSize) 1385 } 1386 1387 // Grow into the current arena. 1388 v := h.curArena.base 1389 h.curArena.base = nBase 1390 h.pages.grow(v, nBase-v) 1391 totalGrowth += nBase - v 1392 1393 // We just caused a heap growth, so scavenge down what will soon be used. 1394 // By scavenging inline we deal with the failure to allocate out of 1395 // memory fragments by scavenging the memory fragments that are least 1396 // likely to be re-used. 1397 if retained := heapRetained(); retained+uint64(totalGrowth) > h.scavengeGoal { 1398 todo := totalGrowth 1399 if overage := uintptr(retained + uint64(totalGrowth) - h.scavengeGoal); todo > overage { 1400 todo = overage 1401 } 1402 h.pages.scavenge(todo, false) 1403 } 1404 return true 1405} 1406 1407// Free the span back into the heap. 1408func (h *mheap) freeSpan(s *mspan) { 1409 systemstack(func() { 1410 lock(&h.lock) 1411 if msanenabled { 1412 // Tell msan that this entire span is no longer in use. 1413 base := unsafe.Pointer(s.base()) 1414 bytes := s.npages << _PageShift 1415 msanfree(base, bytes) 1416 } 1417 h.freeSpanLocked(s, spanAllocHeap) 1418 unlock(&h.lock) 1419 }) 1420} 1421 1422// freeManual frees a manually-managed span returned by allocManual. 1423// typ must be the same as the spanAllocType passed to the allocManual that 1424// allocated s. 1425// 1426// This must only be called when gcphase == _GCoff. See mSpanState for 1427// an explanation. 1428// 1429// freeManual must be called on the system stack because it acquires 1430// the heap lock. See mheap for details. 1431// 1432//go:systemstack 1433func (h *mheap) freeManual(s *mspan, typ spanAllocType) { 1434 s.needzero = 1 1435 lock(&h.lock) 1436 h.freeSpanLocked(s, typ) 1437 unlock(&h.lock) 1438} 1439 1440func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { 1441 assertLockHeld(&h.lock) 1442 1443 switch s.state.get() { 1444 case mSpanManual: 1445 if s.allocCount != 0 { 1446 throw("mheap.freeSpanLocked - invalid stack free") 1447 } 1448 case mSpanInUse: 1449 if s.allocCount != 0 || s.sweepgen != h.sweepgen { 1450 print("mheap.freeSpanLocked - span ", s, " ptr ", hex(s.base()), " allocCount ", s.allocCount, " sweepgen ", s.sweepgen, "/", h.sweepgen, "\n") 1451 throw("mheap.freeSpanLocked - invalid free") 1452 } 1453 atomic.Xadd64(&h.pagesInUse, -int64(s.npages)) 1454 1455 // Clear in-use bit in arena page bitmap. 1456 arena, pageIdx, pageMask := pageIndexOf(s.base()) 1457 atomic.And8(&arena.pageInUse[pageIdx], ^pageMask) 1458 default: 1459 throw("mheap.freeSpanLocked - invalid span state") 1460 } 1461 1462 // Update stats. 1463 // 1464 // Mirrors the code in allocSpan. 1465 nbytes := s.npages * pageSize 1466 if typ == spanAllocHeap { 1467 atomic.Xadd64(&memstats.heap_inuse, -int64(nbytes)) 1468 } 1469 if typ.manual() { 1470 // Manually managed memory doesn't count toward heap_sys, so add it back. 1471 memstats.heap_sys.add(int64(nbytes)) 1472 } 1473 // Update consistent stats. 1474 stats := memstats.heapStats.acquire() 1475 switch typ { 1476 case spanAllocHeap: 1477 atomic.Xaddint64(&stats.inHeap, -int64(nbytes)) 1478 case spanAllocStack: 1479 atomic.Xaddint64(&stats.inStacks, -int64(nbytes)) 1480 case spanAllocPtrScalarBits: 1481 atomic.Xaddint64(&stats.inPtrScalarBits, -int64(nbytes)) 1482 case spanAllocWorkBuf: 1483 atomic.Xaddint64(&stats.inWorkBufs, -int64(nbytes)) 1484 } 1485 memstats.heapStats.release() 1486 1487 // Mark the space as free. 1488 h.pages.free(s.base(), s.npages) 1489 1490 // Free the span structure. We no longer have a use for it. 1491 s.state.set(mSpanDead) 1492 h.freeMSpanLocked(s) 1493} 1494 1495// scavengeAll acquires the heap lock (blocking any additional 1496// manipulation of the page allocator) and iterates over the whole 1497// heap, scavenging every free page available. 1498func (h *mheap) scavengeAll() { 1499 // Disallow malloc or panic while holding the heap lock. We do 1500 // this here because this is a non-mallocgc entry-point to 1501 // the mheap API. 1502 gp := getg() 1503 gp.m.mallocing++ 1504 lock(&h.lock) 1505 // Start a new scavenge generation so we have a chance to walk 1506 // over the whole heap. 1507 h.pages.scavengeStartGen() 1508 released := h.pages.scavenge(^uintptr(0), false) 1509 gen := h.pages.scav.gen 1510 unlock(&h.lock) 1511 gp.m.mallocing-- 1512 1513 if debug.scavtrace > 0 { 1514 printScavTrace(gen, released, true) 1515 } 1516} 1517 1518//go:linkname runtime_debug_freeOSMemory runtime_1debug.freeOSMemory 1519func runtime_debug_freeOSMemory() { 1520 GC() 1521 systemstack(func() { mheap_.scavengeAll() }) 1522} 1523 1524// Initialize a new span with the given start and npages. 1525func (span *mspan) init(base uintptr, npages uintptr) { 1526 // span is *not* zeroed. 1527 span.next = nil 1528 span.prev = nil 1529 span.list = nil 1530 span.startAddr = base 1531 span.npages = npages 1532 span.allocCount = 0 1533 span.spanclass = 0 1534 span.elemsize = 0 1535 span.speciallock.key = 0 1536 span.specials = nil 1537 span.needzero = 0 1538 span.freeindex = 0 1539 span.allocBits = nil 1540 span.gcmarkBits = nil 1541 span.state.set(mSpanDead) 1542 lockInit(&span.speciallock, lockRankMspanSpecial) 1543} 1544 1545func (span *mspan) inList() bool { 1546 return span.list != nil 1547} 1548 1549// Initialize an empty doubly-linked list. 1550func (list *mSpanList) init() { 1551 list.first = nil 1552 list.last = nil 1553} 1554 1555func (list *mSpanList) remove(span *mspan) { 1556 if span.list != list { 1557 print("runtime: failed mSpanList.remove span.npages=", span.npages, 1558 " span=", span, " prev=", span.prev, " span.list=", span.list, " list=", list, "\n") 1559 throw("mSpanList.remove") 1560 } 1561 if list.first == span { 1562 list.first = span.next 1563 } else { 1564 span.prev.next = span.next 1565 } 1566 if list.last == span { 1567 list.last = span.prev 1568 } else { 1569 span.next.prev = span.prev 1570 } 1571 span.next = nil 1572 span.prev = nil 1573 span.list = nil 1574} 1575 1576func (list *mSpanList) isEmpty() bool { 1577 return list.first == nil 1578} 1579 1580func (list *mSpanList) insert(span *mspan) { 1581 if span.next != nil || span.prev != nil || span.list != nil { 1582 println("runtime: failed mSpanList.insert", span, span.next, span.prev, span.list) 1583 throw("mSpanList.insert") 1584 } 1585 span.next = list.first 1586 if list.first != nil { 1587 // The list contains at least one span; link it in. 1588 // The last span in the list doesn't change. 1589 list.first.prev = span 1590 } else { 1591 // The list contains no spans, so this is also the last span. 1592 list.last = span 1593 } 1594 list.first = span 1595 span.list = list 1596} 1597 1598func (list *mSpanList) insertBack(span *mspan) { 1599 if span.next != nil || span.prev != nil || span.list != nil { 1600 println("runtime: failed mSpanList.insertBack", span, span.next, span.prev, span.list) 1601 throw("mSpanList.insertBack") 1602 } 1603 span.prev = list.last 1604 if list.last != nil { 1605 // The list contains at least one span. 1606 list.last.next = span 1607 } else { 1608 // The list contains no spans, so this is also the first span. 1609 list.first = span 1610 } 1611 list.last = span 1612 span.list = list 1613} 1614 1615// takeAll removes all spans from other and inserts them at the front 1616// of list. 1617func (list *mSpanList) takeAll(other *mSpanList) { 1618 if other.isEmpty() { 1619 return 1620 } 1621 1622 // Reparent everything in other to list. 1623 for s := other.first; s != nil; s = s.next { 1624 s.list = list 1625 } 1626 1627 // Concatenate the lists. 1628 if list.isEmpty() { 1629 *list = *other 1630 } else { 1631 // Neither list is empty. Put other before list. 1632 other.last.next = list.first 1633 list.first.prev = other.last 1634 list.first = other.first 1635 } 1636 1637 other.first, other.last = nil, nil 1638} 1639 1640const ( 1641 _KindSpecialFinalizer = 1 1642 _KindSpecialProfile = 2 1643 // Note: The finalizer special must be first because if we're freeing 1644 // an object, a finalizer special will cause the freeing operation 1645 // to abort, and we want to keep the other special records around 1646 // if that happens. 1647) 1648 1649//go:notinheap 1650type special struct { 1651 next *special // linked list in span 1652 offset uint16 // span offset of object 1653 kind byte // kind of special 1654} 1655 1656// spanHasSpecials marks a span as having specials in the arena bitmap. 1657func spanHasSpecials(s *mspan) { 1658 arenaPage := (s.base() / pageSize) % pagesPerArena 1659 ai := arenaIndex(s.base()) 1660 ha := mheap_.arenas[ai.l1()][ai.l2()] 1661 atomic.Or8(&ha.pageSpecials[arenaPage/8], uint8(1)<<(arenaPage%8)) 1662} 1663 1664// spanHasNoSpecials marks a span as having no specials in the arena bitmap. 1665func spanHasNoSpecials(s *mspan) { 1666 arenaPage := (s.base() / pageSize) % pagesPerArena 1667 ai := arenaIndex(s.base()) 1668 ha := mheap_.arenas[ai.l1()][ai.l2()] 1669 atomic.And8(&ha.pageSpecials[arenaPage/8], ^(uint8(1) << (arenaPage % 8))) 1670} 1671 1672// Adds the special record s to the list of special records for 1673// the object p. All fields of s should be filled in except for 1674// offset & next, which this routine will fill in. 1675// Returns true if the special was successfully added, false otherwise. 1676// (The add will fail only if a record with the same p and s->kind 1677// already exists.) 1678func addspecial(p unsafe.Pointer, s *special) bool { 1679 span := spanOfHeap(uintptr(p)) 1680 if span == nil { 1681 throw("addspecial on invalid pointer") 1682 } 1683 1684 // Ensure that the span is swept. 1685 // Sweeping accesses the specials list w/o locks, so we have 1686 // to synchronize with it. And it's just much safer. 1687 mp := acquirem() 1688 span.ensureSwept() 1689 1690 offset := uintptr(p) - span.base() 1691 kind := s.kind 1692 1693 lock(&span.speciallock) 1694 1695 // Find splice point, check for existing record. 1696 t := &span.specials 1697 for { 1698 x := *t 1699 if x == nil { 1700 break 1701 } 1702 if offset == uintptr(x.offset) && kind == x.kind { 1703 unlock(&span.speciallock) 1704 releasem(mp) 1705 return false // already exists 1706 } 1707 if offset < uintptr(x.offset) || (offset == uintptr(x.offset) && kind < x.kind) { 1708 break 1709 } 1710 t = &x.next 1711 } 1712 1713 // Splice in record, fill in offset. 1714 s.offset = uint16(offset) 1715 s.next = *t 1716 *t = s 1717 spanHasSpecials(span) 1718 unlock(&span.speciallock) 1719 releasem(mp) 1720 1721 return true 1722} 1723 1724// Removes the Special record of the given kind for the object p. 1725// Returns the record if the record existed, nil otherwise. 1726// The caller must FixAlloc_Free the result. 1727func removespecial(p unsafe.Pointer, kind uint8) *special { 1728 span := spanOfHeap(uintptr(p)) 1729 if span == nil { 1730 throw("removespecial on invalid pointer") 1731 } 1732 1733 // Ensure that the span is swept. 1734 // Sweeping accesses the specials list w/o locks, so we have 1735 // to synchronize with it. And it's just much safer. 1736 mp := acquirem() 1737 span.ensureSwept() 1738 1739 offset := uintptr(p) - span.base() 1740 1741 var result *special 1742 lock(&span.speciallock) 1743 t := &span.specials 1744 for { 1745 s := *t 1746 if s == nil { 1747 break 1748 } 1749 // This function is used for finalizers only, so we don't check for 1750 // "interior" specials (p must be exactly equal to s->offset). 1751 if offset == uintptr(s.offset) && kind == s.kind { 1752 *t = s.next 1753 result = s 1754 break 1755 } 1756 t = &s.next 1757 } 1758 if span.specials == nil { 1759 spanHasNoSpecials(span) 1760 } 1761 unlock(&span.speciallock) 1762 releasem(mp) 1763 return result 1764} 1765 1766// The described object has a finalizer set for it. 1767// 1768// specialfinalizer is allocated from non-GC'd memory, so any heap 1769// pointers must be specially handled. 1770// 1771//go:notinheap 1772type specialfinalizer struct { 1773 special special 1774 fn *funcval // May be a heap pointer. 1775 ft *functype // May be a heap pointer, but always live. 1776 ot *ptrtype // May be a heap pointer, but always live. 1777} 1778 1779// Adds a finalizer to the object p. Returns true if it succeeded. 1780func addfinalizer(p unsafe.Pointer, f *funcval, ft *functype, ot *ptrtype) bool { 1781 lock(&mheap_.speciallock) 1782 s := (*specialfinalizer)(mheap_.specialfinalizeralloc.alloc()) 1783 unlock(&mheap_.speciallock) 1784 s.special.kind = _KindSpecialFinalizer 1785 s.fn = f 1786 s.ft = ft 1787 s.ot = ot 1788 if addspecial(p, &s.special) { 1789 // This is responsible for maintaining the same 1790 // GC-related invariants as markrootSpans in any 1791 // situation where it's possible that markrootSpans 1792 // has already run but mark termination hasn't yet. 1793 if gcphase != _GCoff { 1794 base, _, _ := findObject(uintptr(p), 0, 0, false) 1795 mp := acquirem() 1796 gcw := &mp.p.ptr().gcw 1797 // Mark everything reachable from the object 1798 // so it's retained for the finalizer. 1799 scanobject(base, gcw) 1800 // Mark the finalizer itself, since the 1801 // special isn't part of the GC'd heap. 1802 scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw) 1803 releasem(mp) 1804 } 1805 return true 1806 } 1807 1808 // There was an old finalizer 1809 lock(&mheap_.speciallock) 1810 mheap_.specialfinalizeralloc.free(unsafe.Pointer(s)) 1811 unlock(&mheap_.speciallock) 1812 return false 1813} 1814 1815// Removes the finalizer (if any) from the object p. 1816func removefinalizer(p unsafe.Pointer) { 1817 s := (*specialfinalizer)(unsafe.Pointer(removespecial(p, _KindSpecialFinalizer))) 1818 if s == nil { 1819 return // there wasn't a finalizer to remove 1820 } 1821 lock(&mheap_.speciallock) 1822 mheap_.specialfinalizeralloc.free(unsafe.Pointer(s)) 1823 unlock(&mheap_.speciallock) 1824} 1825 1826// The described object is being heap profiled. 1827// 1828//go:notinheap 1829type specialprofile struct { 1830 special special 1831 b *bucket 1832} 1833 1834// Set the heap profile bucket associated with addr to b. 1835func setprofilebucket(p unsafe.Pointer, b *bucket) { 1836 lock(&mheap_.speciallock) 1837 s := (*specialprofile)(mheap_.specialprofilealloc.alloc()) 1838 unlock(&mheap_.speciallock) 1839 s.special.kind = _KindSpecialProfile 1840 s.b = b 1841 if !addspecial(p, &s.special) { 1842 throw("setprofilebucket: profile already set") 1843 } 1844} 1845 1846// Do whatever cleanup needs to be done to deallocate s. It has 1847// already been unlinked from the mspan specials list. 1848func freespecial(s *special, p unsafe.Pointer, size uintptr) { 1849 switch s.kind { 1850 case _KindSpecialFinalizer: 1851 sf := (*specialfinalizer)(unsafe.Pointer(s)) 1852 queuefinalizer(p, sf.fn, sf.ft, sf.ot) 1853 lock(&mheap_.speciallock) 1854 mheap_.specialfinalizeralloc.free(unsafe.Pointer(sf)) 1855 unlock(&mheap_.speciallock) 1856 case _KindSpecialProfile: 1857 sp := (*specialprofile)(unsafe.Pointer(s)) 1858 mProf_Free(sp.b, size) 1859 lock(&mheap_.speciallock) 1860 mheap_.specialprofilealloc.free(unsafe.Pointer(sp)) 1861 unlock(&mheap_.speciallock) 1862 default: 1863 throw("bad special kind") 1864 panic("not reached") 1865 } 1866} 1867 1868// gcBits is an alloc/mark bitmap. This is always used as *gcBits. 1869// 1870//go:notinheap 1871type gcBits uint8 1872 1873// bytep returns a pointer to the n'th byte of b. 1874func (b *gcBits) bytep(n uintptr) *uint8 { 1875 return addb((*uint8)(b), n) 1876} 1877 1878// bitp returns a pointer to the byte containing bit n and a mask for 1879// selecting that bit from *bytep. 1880func (b *gcBits) bitp(n uintptr) (bytep *uint8, mask uint8) { 1881 return b.bytep(n / 8), 1 << (n % 8) 1882} 1883 1884const gcBitsChunkBytes = uintptr(64 << 10) 1885const gcBitsHeaderBytes = unsafe.Sizeof(gcBitsHeader{}) 1886 1887type gcBitsHeader struct { 1888 free uintptr // free is the index into bits of the next free byte. 1889 next uintptr // *gcBits triggers recursive type bug. (issue 14620) 1890} 1891 1892//go:notinheap 1893type gcBitsArena struct { 1894 // gcBitsHeader // side step recursive type bug (issue 14620) by including fields by hand. 1895 free uintptr // free is the index into bits of the next free byte; read/write atomically 1896 next *gcBitsArena 1897 bits [gcBitsChunkBytes - gcBitsHeaderBytes]gcBits 1898} 1899 1900var gcBitsArenas struct { 1901 lock mutex 1902 free *gcBitsArena 1903 next *gcBitsArena // Read atomically. Write atomically under lock. 1904 current *gcBitsArena 1905 previous *gcBitsArena 1906} 1907 1908// tryAlloc allocates from b or returns nil if b does not have enough room. 1909// This is safe to call concurrently. 1910func (b *gcBitsArena) tryAlloc(bytes uintptr) *gcBits { 1911 if b == nil || atomic.Loaduintptr(&b.free)+bytes > uintptr(len(b.bits)) { 1912 return nil 1913 } 1914 // Try to allocate from this block. 1915 end := atomic.Xadduintptr(&b.free, bytes) 1916 if end > uintptr(len(b.bits)) { 1917 return nil 1918 } 1919 // There was enough room. 1920 start := end - bytes 1921 return &b.bits[start] 1922} 1923 1924// newMarkBits returns a pointer to 8 byte aligned bytes 1925// to be used for a span's mark bits. 1926func newMarkBits(nelems uintptr) *gcBits { 1927 blocksNeeded := uintptr((nelems + 63) / 64) 1928 bytesNeeded := blocksNeeded * 8 1929 1930 // Try directly allocating from the current head arena. 1931 head := (*gcBitsArena)(atomic.Loadp(unsafe.Pointer(&gcBitsArenas.next))) 1932 if p := head.tryAlloc(bytesNeeded); p != nil { 1933 return p 1934 } 1935 1936 // There's not enough room in the head arena. We may need to 1937 // allocate a new arena. 1938 lock(&gcBitsArenas.lock) 1939 // Try the head arena again, since it may have changed. Now 1940 // that we hold the lock, the list head can't change, but its 1941 // free position still can. 1942 if p := gcBitsArenas.next.tryAlloc(bytesNeeded); p != nil { 1943 unlock(&gcBitsArenas.lock) 1944 return p 1945 } 1946 1947 // Allocate a new arena. This may temporarily drop the lock. 1948 fresh := newArenaMayUnlock() 1949 // If newArenaMayUnlock dropped the lock, another thread may 1950 // have put a fresh arena on the "next" list. Try allocating 1951 // from next again. 1952 if p := gcBitsArenas.next.tryAlloc(bytesNeeded); p != nil { 1953 // Put fresh back on the free list. 1954 // TODO: Mark it "already zeroed" 1955 fresh.next = gcBitsArenas.free 1956 gcBitsArenas.free = fresh 1957 unlock(&gcBitsArenas.lock) 1958 return p 1959 } 1960 1961 // Allocate from the fresh arena. We haven't linked it in yet, so 1962 // this cannot race and is guaranteed to succeed. 1963 p := fresh.tryAlloc(bytesNeeded) 1964 if p == nil { 1965 throw("markBits overflow") 1966 } 1967 1968 // Add the fresh arena to the "next" list. 1969 fresh.next = gcBitsArenas.next 1970 atomic.StorepNoWB(unsafe.Pointer(&gcBitsArenas.next), unsafe.Pointer(fresh)) 1971 1972 unlock(&gcBitsArenas.lock) 1973 return p 1974} 1975 1976// newAllocBits returns a pointer to 8 byte aligned bytes 1977// to be used for this span's alloc bits. 1978// newAllocBits is used to provide newly initialized spans 1979// allocation bits. For spans not being initialized the 1980// mark bits are repurposed as allocation bits when 1981// the span is swept. 1982func newAllocBits(nelems uintptr) *gcBits { 1983 return newMarkBits(nelems) 1984} 1985 1986// nextMarkBitArenaEpoch establishes a new epoch for the arenas 1987// holding the mark bits. The arenas are named relative to the 1988// current GC cycle which is demarcated by the call to finishweep_m. 1989// 1990// All current spans have been swept. 1991// During that sweep each span allocated room for its gcmarkBits in 1992// gcBitsArenas.next block. gcBitsArenas.next becomes the gcBitsArenas.current 1993// where the GC will mark objects and after each span is swept these bits 1994// will be used to allocate objects. 1995// gcBitsArenas.current becomes gcBitsArenas.previous where the span's 1996// gcAllocBits live until all the spans have been swept during this GC cycle. 1997// The span's sweep extinguishes all the references to gcBitsArenas.previous 1998// by pointing gcAllocBits into the gcBitsArenas.current. 1999// The gcBitsArenas.previous is released to the gcBitsArenas.free list. 2000func nextMarkBitArenaEpoch() { 2001 lock(&gcBitsArenas.lock) 2002 if gcBitsArenas.previous != nil { 2003 if gcBitsArenas.free == nil { 2004 gcBitsArenas.free = gcBitsArenas.previous 2005 } else { 2006 // Find end of previous arenas. 2007 last := gcBitsArenas.previous 2008 for last = gcBitsArenas.previous; last.next != nil; last = last.next { 2009 } 2010 last.next = gcBitsArenas.free 2011 gcBitsArenas.free = gcBitsArenas.previous 2012 } 2013 } 2014 gcBitsArenas.previous = gcBitsArenas.current 2015 gcBitsArenas.current = gcBitsArenas.next 2016 atomic.StorepNoWB(unsafe.Pointer(&gcBitsArenas.next), nil) // newMarkBits calls newArena when needed 2017 unlock(&gcBitsArenas.lock) 2018} 2019 2020// newArenaMayUnlock allocates and zeroes a gcBits arena. 2021// The caller must hold gcBitsArena.lock. This may temporarily release it. 2022func newArenaMayUnlock() *gcBitsArena { 2023 var result *gcBitsArena 2024 if gcBitsArenas.free == nil { 2025 unlock(&gcBitsArenas.lock) 2026 result = (*gcBitsArena)(sysAlloc(gcBitsChunkBytes, &memstats.gcMiscSys)) 2027 if result == nil { 2028 throw("runtime: cannot allocate memory") 2029 } 2030 lock(&gcBitsArenas.lock) 2031 } else { 2032 result = gcBitsArenas.free 2033 gcBitsArenas.free = gcBitsArenas.free.next 2034 memclrNoHeapPointers(unsafe.Pointer(result), gcBitsChunkBytes) 2035 } 2036 result.next = nil 2037 // If result.bits is not 8 byte aligned adjust index so 2038 // that &result.bits[result.free] is 8 byte aligned. 2039 if uintptr(unsafe.Offsetof(gcBitsArena{}.bits))&7 == 0 { 2040 result.free = 0 2041 } else { 2042 result.free = 8 - (uintptr(unsafe.Pointer(&result.bits[0])) & 7) 2043 } 2044 return result 2045} 2046