diff --git a/rmm/src/allocator/frame/bump.rs b/rmm/src/allocator/frame/bump.rs
index c0c1ade5b0..375434bfec 100644
--- a/rmm/src/allocator/frame/bump.rs
+++ b/rmm/src/allocator/frame/bump.rs
@@ -1,11 +1,23 @@
-use core::marker::PhantomData;
+use core::{
+ marker::PhantomData,
+ ptr::null_mut,
+};
use crate::{Arch, FrameAllocator, FrameCount, FrameUsage, MemoryArea, PhysicalAddress};
+struct FreeNode {
+ next: *mut FreeNode,
+ count: FrameCount,
+ phys: PhysicalAddress,
+ _marker: PhantomData A>,
+}
+
#[derive(Debug)]
pub struct BumpAllocator {
orig_areas: (&'static [MemoryArea], usize),
cur_areas: (&'static [MemoryArea], usize),
+ free_list: *mut FreeNode,
+ freed_frames: usize,
_marker: PhantomData A>,
}
@@ -21,6 +33,8 @@ impl BumpAllocator {
Self {
orig_areas: (areas, offset),
cur_areas: (areas, offset),
+ free_list: null_mut(),
+ freed_frames: 0,
_marker: PhantomData,
}
}
@@ -48,6 +62,41 @@ unsafe impl FrameAllocator for BumpAllocator {
unsafe {
let req_size = count.data() * A::PAGE_SIZE;
+ let mut prev: *mut FreeNode = null_mut();
+ let mut cur = self.free_list;
+ while !cur.is_null() {
+ let cur_ref = &*cur;
+ let cur_count = cur_ref.count.data();
+ if cur_count >= count.data() {
+ let phys = cur_ref.phys;
+ if cur_count == count.data() {
+ if prev.is_null() {
+ self.free_list = cur_ref.next;
+ } else {
+ (*prev).next = cur_ref.next;
+ }
+ self.freed_frames -= count.data();
+ } else {
+ let new_phys = phys.add(req_size);
+ let new_count = FrameCount::new(cur_count - count.data());
+ let new_node_ptr = A::phys_to_virt(new_phys).data() as *mut FreeNode;
+ (*new_node_ptr).next = cur_ref.next;
+ (*new_node_ptr).count = new_count;
+ (*new_node_ptr).phys = new_phys;
+
+ if prev.is_null() {
+ self.free_list = new_node_ptr;
+ } else {
+ (*prev).next = new_node_ptr;
+ }
+ self.freed_frames -= count.data();
+ }
+ return Some(phys);
+ }
+ prev = cur;
+ cur = cur_ref.next;
+ }
+
let block = loop {
let area = self.cur_areas.0.first()?;
let off = self.cur_areas.1;
@@ -64,15 +113,25 @@ unsafe impl FrameAllocator for BumpAllocator {
}
}
- unsafe fn free(&mut self, _address: PhysicalAddress, _count: FrameCount) {
- unimplemented!("BumpAllocator::free not implemented");
+ unsafe fn free(&mut self, address: PhysicalAddress, count: FrameCount) {
+ let node_ptr = A::phys_to_virt(address).data() as *mut FreeNode;
+ unsafe {
+ (*node_ptr).next = self.free_list;
+ (*node_ptr).count = count;
+ (*node_ptr).phys = address;
+ self.free_list = node_ptr;
+ self.freed_frames += count.data();
+ }
}
fn usage(&self) -> FrameUsage {
let total = self.orig_areas.0.iter().map(|a| a.size).sum::() - self.orig_areas.1;
- let free = self.cur_areas.0.iter().map(|a| a.size).sum::() - self.cur_areas.1;
+ let bump_free =
+ self.cur_areas.0.iter().map(|a| a.size).sum::() - self.cur_areas.1;
+ let bump_used = total - bump_free;
+ let used = bump_used - (self.freed_frames * A::PAGE_SIZE);
FrameUsage::new(
- FrameCount::new((total - free) / A::PAGE_SIZE),
+ FrameCount::new(used / A::PAGE_SIZE),
FrameCount::new(total / A::PAGE_SIZE),
)
}