From 0e3857ca507d36dbdb08c8c14a24a5c165f38e66 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 18 Apr 2017 18:16:03 +0200 Subject: [PATCH] Create a stack allocator module --- src/memory/mod.rs | 1 + src/memory/paging/mod.rs | 3 +- src/memory/stack_allocator.rs | 79 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/memory/stack_allocator.rs diff --git a/src/memory/mod.rs b/src/memory/mod.rs index d589e9a..631228d 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -6,6 +6,7 @@ use multiboot2::BootInformation; mod area_frame_allocator; pub mod heap_allocator; mod paging; +mod stack_allocator; pub const PAGE_SIZE: usize = 4096; diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs index 35d1b5d..98b150c 100644 --- a/src/memory/paging/mod.rs +++ b/src/memory/paging/mod.rs @@ -30,7 +30,7 @@ impl Page { Page { number: address / PAGE_SIZE } } - fn start_address(&self) -> usize { + pub fn start_address(&self) -> usize { self.number * PAGE_SIZE } @@ -55,6 +55,7 @@ impl Page { } } +#[derive(Clone)] pub struct PageIter { start: Page, end: Page, diff --git a/src/memory/stack_allocator.rs b/src/memory/stack_allocator.rs new file mode 100644 index 0000000..efb6696 --- /dev/null +++ b/src/memory/stack_allocator.rs @@ -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(&mut self, + active_table: &mut ActivePageTable, + frame_allocator: &mut FA, + size_in_pages: usize) + -> Option { + 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 + } +}