MCPcopy
hub / github.com/google/gvisor / Allocate

Method Allocate

pkg/sentry/pgalloc/pgalloc.go:649–770  ·  view source on GitHub ↗

Allocate returns a range of initially-zeroed pages of the given length, with a single reference on each page held by the caller. When the last reference on an allocated page is released, ownership of the page is returned to the MemoryFile, allowing it to be returned by a future call to Allocate. Pr

(length uint64, opts AllocOpts)

Source from the content-addressed store, hash-verified

647// - length must be page-aligned.
648// - If opts.Hugepage == true, length must be hugepage-aligned.
649func (f *MemoryFile) Allocate(length uint64, opts AllocOpts) (memmap.FileRange, error) {
650 if length == 0 || !hostarch.IsPageAligned(length) || (opts.Huge && !hostarch.IsHugePageAligned(length)) {
651 panic(fmt.Sprintf("invalid allocation length: %#x", length))
652 }
653
654 alloc := allocState{
655 length: length,
656 opts: opts,
657 willCommit: opts.Mode != AllocateUncommitted,
658 huge: opts.Huge && f.opts.ExpectHugepages,
659 }
660
661 fr, err := f.findAllocatableAndMarkUsed(&alloc)
662 if err != nil {
663 return fr, err
664 }
665
666 var dsts safemem.BlockSeq
667 if alloc.willCommit {
668 needHugeTouch := false
669 if alloc.recycled {
670 // We will need writable page table entries in our address space to
671 // zero these pages.
672 alloc.opts.Mode = AllocateAndWritePopulate
673 } else if alloc.opts.Mode != AllocateAndWritePopulate && ((alloc.huge && f.opts.AdviseHugepage) || (!alloc.huge && f.opts.AdviseNoHugepage)) {
674 // If Mode is AllocateCallerIndirectCommit and we do nothing, the
675 // first access to the allocation may be by the application,
676 // through a platform.AddressSpace, which may not have
677 // MADV_HUGEPAGE (=> vma flag VM_HUGEPAGE) set. Consequently,
678 // shmem_fault() => shmem_get_folio_gfp() will commit a small page.
679 //
680 // If Mode is AllocateAndCommit and we do nothing, the first access
681 // to the allocation is via fallocate(2), which has the same
682 // problem: shmem_fallocate() => shmem_get_folio() =>
683 // shmem_get_folio_gfp(vma=NULL).
684 //
685 // khugepaged may eventually collapse the containing
686 // hugepage-aligned region into a huge page when it scans our
687 // mapping (khugepaged_scan_mm_slot() => khugepaged_scan_file()),
688 // but this depends on khugepaged_max_ptes_none, and in addition to
689 // the latency and overhead of doing so, this will incur another
690 // round of page faults.
691 //
692 // If write-populating through our mappings succeeds, then it will
693 // avoid this problem. Otherwise, we need to touch each huge page
694 // through our mappings.
695 //
696 // An analogous problem applies if MADV_NOHUGEPAGE is required
697 // rather than MADV_HUGEPAGE; MADV_NOHUGEPAGE is only enabled if
698 // the file defaults to huge pages, so populating or touching
699 // through our mappings is needed to ensure that the allocation is
700 // small-page-backed. In this case, we only need to force
701 // commitment of one small page per huge page to prevent future
702 // page faults within the huge page from faulting a huge page,
703 // though there's nothing we can do about khugepaged.
704 alloc.opts.Mode = AllocateAndWritePopulate
705 needHugeTouch = true
706 }

Callers

nothing calls this directly

Calls 15

commitFileMethod · 0.95
DecRefMethod · 0.95
MapInternalMethod · 0.95
manuallyZeroMethod · 0.95
forEachMappingSliceMethod · 0.95
IsEmptyMethod · 0.95
IsPageAlignedFunction · 0.92
IsHugePageAlignedFunction · 0.92
ReadFullToBlocksFunction · 0.92
AddrTypeAlias · 0.92
canPopulateFunction · 0.85

Tested by

no test coverage detected