From 9b43d615a93c98e3d31a2e13792a1495e2974da3 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Mon, 20 Nov 2023 10:02:17 -0800 Subject: [PATCH] [Zion] Split free physical memory into two lists. Allow partitioning create requests so for large continuous requests we don't have to iterate past a bunch of single free pages. --- zion/memory/physical_memory.cpp | 67 +++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/zion/memory/physical_memory.cpp b/zion/memory/physical_memory.cpp index 526c09f..c66b9e2 100644 --- a/zion/memory/physical_memory.cpp +++ b/zion/memory/physical_memory.cpp @@ -56,20 +56,24 @@ class PhysicalMemoryManager { } uint64_t AllocatePage() { - if (memory_blocks.size() == 0) { + if (single_memory_pages_.size() > 0) { + return single_memory_pages_.PopFront(); + } + + if (memory_blocks_.size() == 0) { panic("No available memory regions."); } - while (memory_blocks.PeekFront().num_pages == 0) { - memory_blocks.PopFront(); + while (memory_blocks_.PeekFront().num_pages == 0) { + memory_blocks_.PopFront(); } - MemBlock& block = memory_blocks.PeekFront(); + MemBlock& block = memory_blocks_.PeekFront(); uint64_t page = block.base; block.base += kPageSize; block.num_pages--; if (block.num_pages == 0) { - memory_blocks.PopFront(); + memory_blocks_.PopFront(); } #if K_PHYS_DEBUG dbgln("Single {x}", page); @@ -78,37 +82,37 @@ class PhysicalMemoryManager { return page; } uint64_t AllocateContinuous(uint64_t num_pages) { - if (memory_blocks.size() == 0) { + if (memory_blocks_.size() == 0) { panic("No available memory regions."); } - MemBlock& block = memory_blocks.PeekFront(); - if (block.num_pages == 0) { - panic("Bad state, empty memory block."); + // TODO: Add an easy way to delete an iterator from a LinkedList + // so we can keep the blocklist free from 0 sized pages. + // These occur when we allocate a continuous block the same size as + // an available MemoryBlock. + while (memory_blocks_.PeekFront().num_pages == 0) { + memory_blocks_.PopFront(); } - auto iter = memory_blocks.begin(); - while (iter != memory_blocks.end() && iter->num_pages < num_pages) { - dbgln("Skipping block of size {} seeking {}", iter->num_pages, num_pages); - iter = iter.next(); - } - - if (iter == memory_blocks.end()) { - panic("No memory regions to allocate"); - } - - uint64_t page = iter->base; - iter->base += num_pages * kPageSize; - iter->num_pages -= num_pages; + for (MemBlock& block : memory_blocks_) { + if (block.num_pages < num_pages) { + continue; + } + uint64_t page = block.base; + block.base += num_pages * kPageSize; + block.num_pages -= num_pages; #if K_PHYS_DEBUG - dbgln("Continuous {x}:{}", page, num_pages); + dbgln("Continuous {x}:{}", page, num_pages); #endif - allocated_pages_ += num_pages; - return page; + return page; + } + + panic("No memory regions to allocate"); + UNREACHABLE } void FreePage(uint64_t page) { - AddMemoryRegion(page, 1); + single_memory_pages_.PushFront(page); allocated_pages_--; } @@ -121,7 +125,7 @@ class PhysicalMemoryManager { uint64_t AvailablePages() { uint64_t available = 0; - for (const auto& mem_block : memory_blocks) { + for (const auto& mem_block : memory_blocks_) { available += mem_block.num_pages; } return available; @@ -133,7 +137,12 @@ class PhysicalMemoryManager { uint64_t num_pages = 0; }; - glcr::LinkedList memory_blocks; + // Memory blocks contains the initial memory blocks + // as well as freed chucks. We relegate single freed + // pages to a separate list to avoid having to traverse far + // to find large ones. + glcr::LinkedList memory_blocks_; + glcr::LinkedList single_memory_pages_; uint64_t allocated_pages_ = 0; @@ -142,7 +151,7 @@ class PhysicalMemoryManager { .base = base, .num_pages = num_pages, }; - memory_blocks.PushFront(block); + memory_blocks_.PushFront(block); } };