mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Create a stack allocator module
This commit is contained in:
@@ -6,6 +6,7 @@ use multiboot2::BootInformation;
|
|||||||
mod area_frame_allocator;
|
mod area_frame_allocator;
|
||||||
pub mod heap_allocator;
|
pub mod heap_allocator;
|
||||||
mod paging;
|
mod paging;
|
||||||
|
mod stack_allocator;
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl Page {
|
|||||||
Page { number: address / PAGE_SIZE }
|
Page { number: address / PAGE_SIZE }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_address(&self) -> usize {
|
pub fn start_address(&self) -> usize {
|
||||||
self.number * PAGE_SIZE
|
self.number * PAGE_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +55,7 @@ impl Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PageIter {
|
pub struct PageIter {
|
||||||
start: Page,
|
start: Page,
|
||||||
end: Page,
|
end: Page,
|
||||||
|
|||||||
79
src/memory/stack_allocator.rs
Normal file
79
src/memory/stack_allocator.rs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
use memory::paging::{self, Page, PageIter, ActivePageTable};
|
||||||
|
use memory::{PAGE_SIZE, FrameAllocator};
|
||||||
|
|
||||||
|
pub struct StackAllocator {
|
||||||
|
range: PageIter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackAllocator {
|
||||||
|
pub fn new(page_range: PageIter) -> StackAllocator {
|
||||||
|
StackAllocator { range: page_range }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackAllocator {
|
||||||
|
pub fn alloc_stack<FA: FrameAllocator>(&mut self,
|
||||||
|
active_table: &mut ActivePageTable,
|
||||||
|
frame_allocator: &mut FA,
|
||||||
|
size_in_pages: usize)
|
||||||
|
-> Option<Stack> {
|
||||||
|
if size_in_pages == 0 {
|
||||||
|
return None; /* a zero sized stack makes no sense */
|
||||||
|
}
|
||||||
|
|
||||||
|
// clone the range, since we only want to change it on success
|
||||||
|
let mut range = self.range.clone();
|
||||||
|
|
||||||
|
// try to allocate the stack pages and a guard page
|
||||||
|
let guard_page = range.next();
|
||||||
|
let stack_start = range.next();
|
||||||
|
let stack_end = if size_in_pages == 1 {
|
||||||
|
stack_start
|
||||||
|
} else {
|
||||||
|
// choose the (size_in_pages-2)th element, since index
|
||||||
|
// starts at 0 and we already allocated the start page
|
||||||
|
range.nth(size_in_pages - 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
match (guard_page, stack_start, stack_end) {
|
||||||
|
(Some(_), Some(start), Some(end)) => {
|
||||||
|
// success! write back updated range
|
||||||
|
self.range = range;
|
||||||
|
|
||||||
|
// map stack pages to physical frames
|
||||||
|
for page in Page::range_inclusive(start, end) {
|
||||||
|
active_table.map(page, paging::WRITABLE, frame_allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new stack
|
||||||
|
let top_of_stack = end.start_address() + PAGE_SIZE;
|
||||||
|
Some(Stack::new(top_of_stack, start.start_address()))
|
||||||
|
}
|
||||||
|
_ => None, /* not enough pages */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Stack {
|
||||||
|
top: usize,
|
||||||
|
bottom: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stack {
|
||||||
|
fn new(top: usize, bottom: usize) -> Stack {
|
||||||
|
assert!(top > bottom);
|
||||||
|
Stack {
|
||||||
|
top: top,
|
||||||
|
bottom: bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn top(&self) -> usize {
|
||||||
|
self.top
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bottom(&self) -> usize {
|
||||||
|
self.bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user