mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: allocator: block: implement reserver function
This commit is contained in:
parent
e9751585fe
commit
9710132b3e
@ -47,6 +47,10 @@ impl<const N: usize> RamBlock<N> {
|
||||
}
|
||||
|
||||
fn insert(&mut self, start: PhysAddr, size: usize) -> Result<&mut Option<Block>, ()> {
|
||||
if size == 0 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
for block in self.blocks.iter_mut() {
|
||||
if block.is_none() {
|
||||
*block = Some(Block { start, size });
|
||||
@ -102,12 +106,42 @@ impl<const N: usize> RamBlock<N> {
|
||||
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use log::debug;
|
||||
|
||||
#[test_case]
|
||||
fn test_block() {
|
||||
@ -150,4 +184,28 @@ mod tests {
|
||||
let ptr = blk.alloc(Layout::from_size_align(1, 1).unwrap());
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -116,10 +116,9 @@ impl FreeList {
|
||||
}
|
||||
|
||||
pub fn reserve(&mut self, start: PhysAddr, size: usize) {
|
||||
// NOTE: only support inclusive range
|
||||
if let Some((region, _)) = self.alloc_node(|region| {
|
||||
let left = max(region.start_addr(), start);
|
||||
let right = min(region.end_addr(), start + size);
|
||||
(left < right).some(|| (), ())
|
||||
(region.start_addr() <= start && start < region.end_addr()).some(|| (), ())
|
||||
}) {
|
||||
let region_start = region.start_addr();
|
||||
let region_end = region.end_addr();
|
||||
|
@ -3,4 +3,5 @@ mod block;
|
||||
mod freelist;
|
||||
|
||||
pub use bitmap::*;
|
||||
pub use block::*;
|
||||
pub use freelist::*;
|
||||
|
Loading…
Reference in New Issue
Block a user