2014-12-24 14:28:21 +08:00
|
|
|
extern crate std;
|
2015-04-16 14:04:06 +08:00
|
|
|
use core::prelude::*;
|
2015-03-27 14:52:25 +08:00
|
|
|
use self::std::io::Error as IoError;
|
2015-01-14 15:31:17 +08:00
|
|
|
use stack;
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-04-16 14:04:06 +08:00
|
|
|
#[cfg(unix)]
|
|
|
|
#[path = "os/unix.rs"] mod sys;
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
#[allow(raw_pointer_derive)]
|
|
|
|
#[derive(Debug)]
|
2014-12-24 14:07:25 +08:00
|
|
|
pub struct Stack {
|
2015-03-27 14:52:25 +08:00
|
|
|
ptr: *mut u8,
|
2015-04-16 14:30:10 +08:00
|
|
|
len: usize
|
2014-12-24 14:07:25 +08:00
|
|
|
}
|
|
|
|
|
2015-04-16 03:56:57 +08:00
|
|
|
pub struct StackSource;
|
|
|
|
|
|
|
|
impl stack::StackSource for StackSource {
|
|
|
|
type Output = Stack;
|
2015-04-16 16:14:18 +08:00
|
|
|
type Error = IoError;
|
|
|
|
|
|
|
|
fn get_stack(size: usize) -> Result<Stack, IoError> {
|
2015-04-16 03:56:57 +08:00
|
|
|
Stack::new(size)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
impl stack::Stack for Stack {
|
|
|
|
fn top(&mut self) -> *mut u8 {
|
|
|
|
unsafe {
|
|
|
|
self.ptr.offset(self.len as isize)
|
|
|
|
}
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
fn limit(&self) -> *const u8 {
|
|
|
|
unsafe {
|
2015-04-16 14:04:06 +08:00
|
|
|
self.ptr.offset(sys::page_size() as isize)
|
2015-03-27 14:52:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
|
|
|
|
impl Stack {
|
2015-04-16 16:14:18 +08:00
|
|
|
fn new(size: usize) -> Result<Stack, IoError> {
|
2015-04-16 14:04:06 +08:00
|
|
|
let page_size = sys::page_size();
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
// round the page size up,
|
|
|
|
// using the fact that it is a power of two
|
|
|
|
let len = (size + page_size - 1) & !(page_size - 1);
|
|
|
|
|
|
|
|
let stack = unsafe {
|
2015-04-16 16:14:18 +08:00
|
|
|
let ptr = try!(match sys::map_stack(size) {
|
|
|
|
None => Err(IoError::last_os_error()),
|
|
|
|
Some(ptr) => Ok(ptr)
|
|
|
|
});
|
2015-03-27 14:52:25 +08:00
|
|
|
|
2015-04-16 14:30:10 +08:00
|
|
|
Stack { ptr: ptr as *mut u8, len: len }
|
2014-12-24 14:07:25 +08:00
|
|
|
};
|
|
|
|
|
2015-04-16 16:14:18 +08:00
|
|
|
try!(unsafe {
|
|
|
|
if sys::protect_stack(stack.ptr) { Ok(()) }
|
|
|
|
else { Err(IoError::last_os_error()) }
|
|
|
|
});
|
2015-04-16 14:04:06 +08:00
|
|
|
|
2015-04-16 16:14:18 +08:00
|
|
|
Ok(stack)
|
2014-12-24 14:07:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
impl Drop for Stack {
|
|
|
|
fn drop(&mut self) {
|
2014-12-24 14:07:25 +08:00
|
|
|
unsafe {
|
2015-04-16 14:04:06 +08:00
|
|
|
if !sys::unmap_stack(self.ptr, self.len) {
|
2015-04-16 14:08:41 +08:00
|
|
|
panic!("munmap for stack {:p} of size {} failed: {}",
|
2015-03-27 14:52:25 +08:00
|
|
|
self.ptr, self.len, IoError::last_os_error())
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-24 13:12:39 +08:00
|
|
|
}
|