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>, ()> {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user