libfringe/src/os.rs

87 lines
1.8 KiB
Rust
Raw Normal View History

extern crate std;
use core::prelude::*;
use self::std::io::Error as IoError;
use stack;
use valgrind;
#[cfg(unix)]
#[path = "os/unix.rs"] mod sys;
#[allow(raw_pointer_derive)]
#[derive(Debug)]
pub struct Stack {
ptr: *mut u8,
len: usize,
valgrind_id: valgrind::stack_id_t
}
pub struct StackSource;
impl stack::StackSource for StackSource {
type Output = Stack;
fn get_stack(size: usize) -> Stack {
Stack::new(size)
}
}
impl stack::Stack for Stack {
fn top(&mut self) -> *mut u8 {
unsafe {
self.ptr.offset(self.len as isize)
}
}
fn limit(&self) -> *const u8 {
unsafe {
self.ptr.offset(sys::page_size() as isize)
}
}
}
impl Stack {
fn new(size: usize) -> Stack {
let page_size = sys::page_size();
// 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 {
let ptr = match sys::map_stack(size) {
None => {
2015-04-16 14:08:41 +08:00
panic!("mmap for stack of size {} failed: {}",
len, IoError::last_os_error())
}
Some(ptr) => ptr
};
let valgrind_id =
valgrind::stack_register(ptr as *const _,
ptr.offset(len as isize) as *const _);
Stack { ptr: ptr as *mut u8, len: len, valgrind_id: valgrind_id }
};
unsafe {
if !sys::protect_stack(stack.ptr) {
2015-04-16 14:08:41 +08:00
panic!("mprotect for guard page of stack {:p} failed: {}",
stack.ptr, IoError::last_os_error());
}
}
stack
}
}
impl Drop for Stack {
fn drop(&mut self) {
unsafe {
valgrind::stack_deregister(self.valgrind_id);
if !sys::unmap_stack(self.ptr, self.len) {
2015-04-16 14:08:41 +08:00
panic!("munmap for stack {:p} of size {} failed: {}",
self.ptr, self.len, IoError::last_os_error())
}
}
}
2014-12-24 13:12:39 +08:00
}