| @ -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 | |||||
| } | |||||
| } | |||||
| } | |||||