feat: allocator: block: implement reserver function

This commit is contained in:
Paul Pan 2024-04-07 01:02:23 +08:00
parent e9751585fe
commit 9710132b3e
3 changed files with 62 additions and 4 deletions

View File

@ -47,6 +47,10 @@ impl<const N: usize> RamBlock<N> {
} }
fn insert(&mut self, start: PhysAddr, size: usize) -> Result<&mut Option<Block>, ()> { fn insert(&mut self, start: PhysAddr, size: usize) -> Result<&mut Option<Block>, ()> {
if size == 0 {
return Err(());
}
for block in self.blocks.iter_mut() { for block in self.blocks.iter_mut() {
if block.is_none() { if block.is_none() {
*block = Some(Block { start, size }); *block = Some(Block { start, size });
@ -102,12 +106,42 @@ impl<const N: usize> RamBlock<N> {
None None
} }
pub fn reserve(&mut self, start: PhysAddr, size: usize) {
// NOTE: only support inclusive range
let victim = self
.blocks
.iter_mut()
.find(|block| block.is_some_and(|b| b.start_addr() <= start && start < b.end_addr()));
if victim.is_none() {
return;
}
let victim = victim.unwrap();
if let Some(block) = victim.take() {
let region_start = block.start_addr();
let region_end = block.end_addr();
let before_size = (start - region_start).as_usize();
let after_size = (region_end - (start + size)).as_usize();
// insert larger block first, then before block, then after block
if after_size > before_size {
// we could safely assert that before_size > 0 here
let _ = self.insert(start + size, after_size);
let _ = self.insert(region_start, before_size);
} else {
let _ = self.insert(region_start, before_size);
let _ = self.insert(start + size, after_size);
}
}
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use log::debug;
#[test_case] #[test_case]
fn test_block() { fn test_block() {
@ -150,4 +184,28 @@ mod tests {
let ptr = blk.alloc(Layout::from_size_align(1, 1).unwrap()); let ptr = blk.alloc(Layout::from_size_align(1, 1).unwrap());
assert_eq!(ptr, None); assert_eq!(ptr, None);
} }
#[test_case]
fn test_block_reserve() {
let mut blk = RamBlock::<4>::new();
blk.dealloc(PhysAddr(0), 100);
blk.reserve(PhysAddr(0), 10);
let ptr = blk.alloc(Layout::from_size_align(10, 1).unwrap());
assert_eq!(ptr, Some(PhysAddr(10)));
blk.reserve(PhysAddr(90), 10);
let ptr = blk.alloc(Layout::from_size_align(70, 1).unwrap());
assert_eq!(ptr, Some(PhysAddr(0x14)));
blk.dealloc(PhysAddr(0), 30);
blk.reserve(PhysAddr(10), 10);
let ptr = blk.alloc(Layout::from_size_align(10, 1).unwrap());
assert_eq!(ptr, Some(PhysAddr(0)));
let ptr = blk.alloc(Layout::from_size_align(10, 1).unwrap());
assert_eq!(ptr, Some(PhysAddr(20)));
let ptr = blk.alloc(Layout::from_size_align(1, 1).unwrap());
assert_eq!(ptr, None);
}
} }

View File

@ -116,10 +116,9 @@ impl FreeList {
} }
pub fn reserve(&mut self, start: PhysAddr, size: usize) { pub fn reserve(&mut self, start: PhysAddr, size: usize) {
// NOTE: only support inclusive range
if let Some((region, _)) = self.alloc_node(|region| { if let Some((region, _)) = self.alloc_node(|region| {
let left = max(region.start_addr(), start); (region.start_addr() <= start && start < region.end_addr()).some(|| (), ())
let right = min(region.end_addr(), start + size);
(left < right).some(|| (), ())
}) { }) {
let region_start = region.start_addr(); let region_start = region.start_addr();
let region_end = region.end_addr(); let region_end = region.end_addr();

View File

@ -3,4 +3,5 @@ mod block;
mod freelist; mod freelist;
pub use bitmap::*; pub use bitmap::*;
pub use block::*;
pub use freelist::*; pub use freelist::*;