diff --git a/src/allocator/frame/bump.rs b/src/allocator/frame/bump.rs
index d3a2b4eac1..85334b4af6 100644
--- a/src/allocator/frame/bump.rs
+++ b/src/allocator/frame/bump.rs
@@ -12,21 +12,44 @@ use crate::{
pub struct BumpAllocator {
areas: &'static [MemoryArea],
offset: usize,
- phantom: PhantomData,
+ abs_offset: PhysicalAddress,
+ _marker: PhantomData A>,
}
impl BumpAllocator {
pub fn new(areas: &'static [MemoryArea], offset: usize) -> Self {
Self {
areas,
- offset,
- phantom: PhantomData,
+ offset: 0,
+ abs_offset: areas[0].base,
+ _marker: PhantomData,
}
}
-
pub fn areas(&self) -> &'static [MemoryArea] {
self.areas
}
+ /// Returns one semifree and the fully free areas. The offset is the number of bytes after
+ /// which the first area is free.
+ pub fn free_areas(&self) -> (&'static [MemoryArea], usize) {
+ let mut areas = self.areas;
+ let mut offset = self.offset;
+
+ loop {
+ let Some(area) = areas.first() else {
+ return (&[], 0);
+ };
+
+ if offset > area.size {
+ areas = &areas[1..];
+ offset -= area.size;
+ } else {
+ return (areas, offset);
+ }
+ }
+ }
+ pub fn abs_offset(&self) -> PhysicalAddress {
+ self.abs_offset
+ }
pub fn offset(&self) -> usize {
self.offset
@@ -38,7 +61,14 @@ impl FrameAllocator for BumpAllocator {
let mut offset = self.offset;
for area in self.areas.iter() {
if offset < area.size {
- if area.size - offset < count.data() {
+ if area.size - offset < count.data() * A::PAGE_SIZE {
+ /*
+ // The area may be too small for this alloc request. In that case, skip to the
+ // next area.
+ self.offset += area.size - offset;
+ offset = 0;
+ continue;
+ */
return None;
}
@@ -46,6 +76,8 @@ impl FrameAllocator for BumpAllocator {
let page_virt = A::phys_to_virt(page_phys);
A::write_bytes(page_virt, 0, count.data() * A::PAGE_SIZE);
self.offset += count.data() * A::PAGE_SIZE;
+
+ self.abs_offset = page_phys;
return Some(page_phys);
}
offset -= area.size;