const pallocChunkPages … const pallocChunkBytes … const logPallocChunkPages … const logPallocChunkBytes … const summaryLevelBits … const summaryL0Bits … const pallocChunksL2Bits … const pallocChunksL1Shift … // maxSearchAddr returns the maximum searchAddr value, which indicates // that the heap has no free space. // // This function exists just to make it clear that this is the maximum address // for the page allocator's search space. See maxOffAddr for details. // // It's a function (rather than a variable) because it needs to be // usable before package runtime's dynamic initialization is complete. // See #51913 for details. func maxSearchAddr() offAddr { … } type chunkIdx … // chunkIndex returns the global index of the palloc chunk containing the // pointer p. func chunkIndex(p uintptr) chunkIdx { … } // chunkBase returns the base address of the palloc chunk at index ci. func chunkBase(ci chunkIdx) uintptr { … } // chunkPageIndex computes the index of the page that contains p, // relative to the chunk which contains p. func chunkPageIndex(p uintptr) uint { … } // l1 returns the index into the first level of (*pageAlloc).chunks. func (i chunkIdx) l1() uint { … } // l2 returns the index into the second level of (*pageAlloc).chunks. func (i chunkIdx) l2() uint { … } // offAddrToLevelIndex converts an address in the offset address space // to the index into summary[level] containing addr. func offAddrToLevelIndex(level int, addr offAddr) int { … } // levelIndexToOffAddr converts an index into summary[level] into // the corresponding address in the offset address space. func levelIndexToOffAddr(level, idx int) offAddr { … } // addrsToSummaryRange converts base and limit pointers into a range // of entries for the given summary level. // // The returned range is inclusive on the lower bound and exclusive on // the upper bound. func addrsToSummaryRange(level int, base, limit uintptr) (lo int, hi int) { … } // blockAlignSummaryRange aligns indices into the given level to that // level's block width (1 << levelBits[level]). It assumes lo is inclusive // and hi is exclusive, and so aligns them down and up respectively. func blockAlignSummaryRange(level int, lo, hi int) (int, int) { … } type pageAlloc … func (p *pageAlloc) init(mheapLock *mutex, sysStat *sysMemStat, test bool) { … } // tryChunkOf returns the bitmap data for the given chunk. // // Returns nil if the chunk data has not been mapped. func (p *pageAlloc) tryChunkOf(ci chunkIdx) *pallocData { … } // chunkOf returns the chunk at the given chunk index. // // The chunk index must be valid or this method may throw. func (p *pageAlloc) chunkOf(ci chunkIdx) *pallocData { … } // grow sets up the metadata for the address range [base, base+size). // It may allocate metadata, in which case *p.sysStat will be updated. // // p.mheapLock must be held. func (p *pageAlloc) grow(base, size uintptr) { … } // enableChunkHugePages enables huge pages for the chunk bitmap mappings (disabled by default). // // This function is idempotent. // // A note on latency: for sufficiently small heaps (<10s of GiB) this function will take constant // time, but may take time proportional to the size of the mapped heap beyond that. // // The heap lock must not be held over this operation, since it will briefly acquire // the heap lock. // // Must be called on the system stack because it acquires the heap lock. // //go:systemstack func (p *pageAlloc) enableChunkHugePages() { … } // update updates heap metadata. It must be called each time the bitmap // is updated. // // If contig is true, update does some optimizations assuming that there was // a contiguous allocation or free between addr and addr+npages. alloc indicates // whether the operation performed was an allocation or a free. // // p.mheapLock must be held. func (p *pageAlloc) update(base, npages uintptr, contig, alloc bool) { … } // allocRange marks the range of memory [base, base+npages*pageSize) as // allocated. It also updates the summaries to reflect the newly-updated // bitmap. // // Returns the amount of scavenged memory in bytes present in the // allocated range. // // p.mheapLock must be held. func (p *pageAlloc) allocRange(base, npages uintptr) uintptr { … } // findMappedAddr returns the smallest mapped offAddr that is // >= addr. That is, if addr refers to mapped memory, then it is // returned. If addr is higher than any mapped region, then // it returns maxOffAddr. // // p.mheapLock must be held. func (p *pageAlloc) findMappedAddr(addr offAddr) offAddr { … } // find searches for the first (address-ordered) contiguous free region of // npages in size and returns a base address for that region. // // It uses p.searchAddr to prune its search and assumes that no palloc chunks // below chunkIndex(p.searchAddr) contain any free memory at all. // // find also computes and returns a candidate p.searchAddr, which may or // may not prune more of the address space than p.searchAddr already does. // This candidate is always a valid p.searchAddr. // // find represents the slow path and the full radix tree search. // // Returns a base address of 0 on failure, in which case the candidate // searchAddr returned is invalid and must be ignored. // // p.mheapLock must be held. func (p *pageAlloc) find(npages uintptr) (uintptr, offAddr) { … } // alloc allocates npages worth of memory from the page heap, returning the base // address for the allocation and the amount of scavenged memory in bytes // contained in the region [base address, base address + npages*pageSize). // // Returns a 0 base address on failure, in which case other returned values // should be ignored. // // p.mheapLock must be held. // // Must run on the system stack because p.mheapLock must be held. // //go:systemstack func (p *pageAlloc) alloc(npages uintptr) (addr uintptr, scav uintptr) { … } // free returns npages worth of memory starting at base back to the page heap. // // p.mheapLock must be held. // // Must run on the system stack because p.mheapLock must be held. // //go:systemstack func (p *pageAlloc) free(base, npages uintptr) { … } const pallocSumBytes … const maxPackedValue … const logMaxPackedValue … const freeChunkSum … type pallocSum … // packPallocSum takes a start, max, and end value and produces a pallocSum. func packPallocSum(start, max, end uint) pallocSum { … } // start extracts the start value from a packed sum. func (p pallocSum) start() uint { … } // max extracts the max value from a packed sum. func (p pallocSum) max() uint { … } // end extracts the end value from a packed sum. func (p pallocSum) end() uint { … } // unpack unpacks all three values from the summary. func (p pallocSum) unpack() (uint, uint, uint) { … } // mergeSummaries merges consecutive summaries which may each represent at // most 1 << logMaxPagesPerSum pages each together into one. func mergeSummaries(sums []pallocSum, logMaxPagesPerSum uint) pallocSum { … }