|
|
@ -0,0 +1,79 @@ |
|
|
|
use memory::paging::{self, Page, PageIter, ActivePageTable};
|
|
|
|
use memory::{PAGE_SIZE, FrameAllocator};
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Stack {
|
|
|
|
top: usize,
|
|
|
|
bottom: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Stack {
|
|
|
|
fn new(top: usize, bottom: usize) -> Stack {
|
|
|
|
assert!(top > bottom,
|
|
|
|
"Stack top must be higher in memory than the bottom");
|
|
|
|
|
|
|
|
Stack {
|
|
|
|
top: top,
|
|
|
|
bottom: bottom,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn top(&self) -> usize { self.top }
|
|
|
|
pub fn bottom(&self) -> usize { self.bottom }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct StackAllocator {
|
|
|
|
range: PageIter,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StackAllocator {
|
|
|
|
pub fn new(page_range: PageIter) -> StackAllocator {
|
|
|
|
StackAllocator { range: page_range }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Allocate a stack.
|
|
|
|
///
|
|
|
|
/// Note: `size` is given in pages.
|
|
|
|
pub fn alloc_stack<A>(&mut self,
|
|
|
|
active_table: &mut ActivePageTable,
|
|
|
|
frame_alloc: &mut A,
|
|
|
|
size: usize) -> Option<Stack>
|
|
|
|
where A: FrameAllocator
|
|
|
|
{
|
|
|
|
// zero-size stacks are nonsensical
|
|
|
|
if size == 0 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut range = self.range.clone();
|
|
|
|
|
|
|
|
// try to alloc stack, guard pages
|
|
|
|
let guard_page = range.next();
|
|
|
|
let stack_start = range.next();
|
|
|
|
let stack_end = if size == 1 {
|
|
|
|
stack_start
|
|
|
|
} else {
|
|
|
|
range.nth(size - 2)
|
|
|
|
};
|
|
|
|
|
|
|
|
match (guard_page, stack_start, stack_end) {
|
|
|
|
(Some(_), Some(start), Some(end)) => {
|
|
|
|
// writeback
|
|
|
|
self.range = range;
|
|
|
|
|
|
|
|
// map stack pages -> physical frames
|
|
|
|
for page in Page::range_inclusive(start, end) {
|
|
|
|
active_table.map(page, paging::WRITABLE, frame_alloc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// create a new stack
|
|
|
|
|
|
|
|
let top = end.start_address() + PAGE_SIZE;
|
|
|
|
|
|
|
|
Some(Stack::new(top, start.start_address()))
|
|
|
|
}
|
|
|
|
_ => None, // whoops not enough frames
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|