Avoid generic impl trait parameters in BootInfoFrameAllocator

This commit is contained in:
Philipp Oppermann
2019-04-30 10:27:22 +02:00
parent 247af45791
commit 180c77d1f4
2 changed files with 37 additions and 30 deletions

View File

@@ -18,7 +18,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
blog_os::init();
let mut mapper = unsafe { memory::init(boot_info.physical_memory_offset) };
let mut frame_allocator = memory::init_frame_allocator(&boot_info.memory_map);
let mut frame_allocator = memory::BootInfoFrameAllocator::init(&boot_info.memory_map);
// map a previously unmapped page
let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));

View File

@@ -23,24 +23,6 @@ pub unsafe fn init(physical_memory_offset: u64) -> impl MapperAllSizes {
MappedPageTable::new(level_4_table, phys_to_virt)
}
/// Create a FrameAllocator from the passed memory map
pub fn init_frame_allocator(
memory_map: &'static MemoryMap,
) -> BootInfoFrameAllocator<impl Iterator<Item = PhysFrame>> {
// get usable regions from memory map
let regions = memory_map
.iter()
.filter(|r| r.region_type == MemoryRegionType::Usable);
// map each region to its address range
let addr_ranges = regions.map(|r| r.range.start_addr()..r.range.end_addr());
// transform to an iterator of frame start addresses
let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096));
// create `PhysFrame` types from the start addresses
let frames = frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr)));
BootInfoFrameAllocator { frames }
}
/// Returns a mutable reference to the active level 4 table.
///
/// This function is unsafe because the caller must guarantee that the
@@ -83,18 +65,43 @@ impl FrameAllocator<Size4KiB> for EmptyFrameAllocator {
}
}
pub struct BootInfoFrameAllocator<I>
where
I: Iterator<Item = PhysFrame>,
{
frames: I,
/// A FrameAllocator that returns usable frames from the bootloader's memory map.
pub struct BootInfoFrameAllocator {
memory_map: &'static MemoryMap,
last_yielded_frame: PhysFrame,
}
impl<I> FrameAllocator<Size4KiB> for BootInfoFrameAllocator<I>
where
I: Iterator<Item = PhysFrame>,
{
fn allocate_frame(&mut self) -> Option<PhysFrame> {
self.frames.next()
impl BootInfoFrameAllocator {
/// Create a FrameAllocator from the passed memory map.
pub fn init(memory_map: &'static MemoryMap) -> Self {
BootInfoFrameAllocator {
memory_map,
last_yielded_frame: PhysFrame::containing_address(PhysAddr::new(0)),
}
}
/// Returns an iterator over the usable frames specified in the memory map.
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> {
// get usable regions from memory map
let regions = self.memory_map.iter();
let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable);
// map each region to its address range
let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr());
// transform to an iterator of frame start addresses
let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096));
// create `PhysFrame` types from the start addresses
frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr)))
}
}
impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
fn allocate_frame(&mut self) -> Option<PhysFrame> {
let usable_frames = self.usable_frames();
let mut frames = usable_frames.filter(|frame| frame > &self.last_yielded_frame);
let frame = frames.next();
if let Some(frame) = frame {
self.last_yielded_frame = frame.clone();
}
frame
}
}