Commit 37f34c5f authored by 只敲代码不玩耍,聪明baka也变傻ᗜˬᗜ's avatar 只敲代码不玩耍,聪明baka也变傻ᗜˬᗜ :man_dancing_tone1:
Browse files

feat: add contiguous frame allocation support and modify deallocation logic to...

feat: add contiguous frame allocation support and modify deallocation logic to keep self.current the largest frame
Showing with 62 additions and 5 deletions
+62 -5
......@@ -21,9 +21,38 @@ impl Drop for TrackedFrame {
}
}
pub struct TrackedFrameRange {
start: PhysicalPageNum,
count: usize,
}
impl TrackedFrameRange {
pub fn new(start: PhysicalPageNum, count: usize) -> Self {
TrackedFrameRange { start, count }
}
pub fn to_range(&self) -> core::ops::Range<usize> {
self.start.as_usize()..(self.start + self.count).as_usize()
}
}
impl Drop for TrackedFrameRange {
fn drop(&mut self) {
for i in 0..self.count {
unsafe {
dealloc_frame_unchecked(self.start + i);
}
}
}
}
trait IFrameAllocator {
fn alloc_frame(&mut self) -> Option<TrackedFrame>;
// Allocates `count` frames and returns them as a vector, no guarantee that the frames are contiguous
fn alloc_frames(&mut self, count: usize) -> Option<Vec<TrackedFrame>>;
// Allocates `count` frames and returns them as a range, guaranteeing that the frames are contiguous
fn alloc_contiguous(&mut self, count: usize) -> Option<TrackedFrameRange>;
fn dealloc(&mut self, frame: &TrackedFrame);
fn dealloc_multiple(&mut self, frames: impl Iterator<Item = TrackedFrame>) {
......@@ -38,6 +67,7 @@ static mut FRAME_ALLOCATOR: Lazy<FrameAllocator> = Lazy::new(FrameAllocator::new
struct FrameAllocator {
top: PhysicalPageNum,
bottom: PhysicalPageNum,
// current should always point to the last frame that can be allocated
current: PhysicalPageNum,
recycled: Vec<PhysicalPageNum>,
}
......@@ -106,24 +136,51 @@ impl IFrameAllocator for FrameAllocator {
match ppn.cmp(&self.current) {
std::cmp::Ordering::Equal => unreachable!("Should panic at the debug build"),
std::cmp::Ordering::Greater => self.recycled.push(ppn),
std::cmp::Ordering::Less => {
let previous = self.current;
std::cmp::Ordering::Less => self.recycled.push(ppn),
std::cmp::Ordering::Greater => {
let old_current = self.current;
// Marks the frames between the <old current> and <new current, the given ppn> as available
for i in old_current.as_usize()..ppn.as_usize() {
self.recycled.push(PhysicalPageNum::from_usize(i));
}
self.current = ppn;
self.recycled.push(previous);
}
}
}
fn alloc_contiguous(&mut self, count: usize) -> Option<TrackedFrameRange> {
let avaliable = self.recycled.len() + (self.top - self.bottom).as_usize();
match count {
count if count <= avaliable => {
let start = self.current;
self.current += count;
Some(TrackedFrameRange { start, count })
}
// Prevent dealloc if we don't have enough frames
_ => None,
}
}
}
pub fn alloc_frame() -> Option<TrackedFrame> {
unsafe { FRAME_ALLOCATOR.alloc_frame() }
}
// Allocates `count` frames and returns them as a vector
// No guarantee that the frames are contiguous
pub fn alloc_frames(count: usize) -> Option<Vec<TrackedFrame>> {
unsafe { FRAME_ALLOCATOR.alloc_frames(count) }
}
// Similar to alloc_frames, but guarantees that the frames are contiguous
pub fn alloc_contiguous(count: usize) -> Option<TrackedFrameRange> {
unsafe { FRAME_ALLOCATOR.alloc_contiguous(count) }
}
pub unsafe fn dealloc_frame_unchecked(frame: PhysicalPageNum) {
drop(TrackedFrame(frame))
}
......
......@@ -7,7 +7,7 @@ extern crate alloc;
pub mod frame;
pub use frame::{alloc_frame, alloc_frames, dealloc_frame_unchecked};
pub use frame::{alloc_frame, alloc_frames, alloc_contiguous, dealloc_frame_unchecked};
use log::debug;
pub fn init(memory_end: usize) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment