move stack creation / destruction into platform

master
edef 2014-12-24 07:07:25 +01:00
parent 3957ac99ae
commit a94bc324fe
3 changed files with 77 additions and 70 deletions

View File

@ -1,5 +1,4 @@
#![feature(default_type_params, macro_rules)]
extern crate libc;
extern crate fn_box;
pub use context::Context;

View File

@ -1,8 +1,75 @@
use libc;
extern crate libc;
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
MapNonStandardFlags};
extern "C" {
#[link_name = "lwt_stack_register"]
pub fn stack_register(start: *const u8, end: *const u8) -> libc::c_uint;
fn stack_register(start: *const u8, end: *const u8) -> libc::c_uint;
#[link_name = "lwt_stack_deregister"]
pub fn stack_deregister(id: libc::c_uint);
fn stack_deregister(id: libc::c_uint);
}
pub struct Stack {
buf: MemoryMap,
valgrind_id: libc::c_uint
}
const STACK_FLAGS: libc::c_int = libc::MAP_STACK
| libc::MAP_PRIVATE
| libc::MAP_ANON;
impl Stack {
pub fn new(size: uint) -> Stack {
let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
MapNonStandardFlags(STACK_FLAGS)]) {
Ok(map) => map,
Err(e) => panic!("mmap for stack of size {} failed: {}", size, e)
};
if !protect_last_page(&buf) {
panic!("Could not memory-protect guard page. stack={}, errno={}",
buf.data(), errno());
}
let valgrind_id = unsafe {
stack_register(buf.data().offset(buf.len() as int) as *const _,
buf.data() as *const _)
};
Stack {
buf: buf,
valgrind_id: valgrind_id
}
}
}
fn protect_last_page(stack: &MemoryMap) -> bool {
unsafe {
let last_page = stack.data() as *mut libc::c_void;
libc::mprotect(last_page, page_size() as libc::size_t,
libc::PROT_NONE) != -1
}
}
impl Drop for Stack {
fn drop(&mut self) {
unsafe {
stack_deregister(self.valgrind_id);
}
}
}
impl Stack {
pub fn top(&mut self) -> *mut u8 {
unsafe {
self.buf.data().offset(self.buf.len() as int)
}
}
pub fn limit(&self) -> *const u8 {
unsafe {
self.buf.data().offset(page_size() as int) as *const _
}
}
}

View File

@ -1,48 +1,16 @@
use libc;
use platform;
use std::ptr;
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
MapNonStandardFlags};
const STACK_FLAGS: libc::c_int = libc::MAP_STACK
| libc::MAP_PRIVATE
| libc::MAP_ANON;
pub enum Stack {
Native {
sp_limit: *const u8
},
Managed {
buf: MemoryMap,
valgrind_id: libc::c_uint
}
Managed(platform::Stack)
}
impl Stack {
pub fn new(size: uint) -> Stack {
let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
MapNonStandardFlags(STACK_FLAGS)]) {
Ok(map) => map,
Err(e) => panic!("mmap for stack of size {} failed: {}", size, e)
};
if !protect_last_page(&buf) {
panic!("Could not memory-protect guard page. stack={}, errno={}",
buf.data(), errno());
}
let valgrind_id = unsafe {
platform::stack_register(buf.data().offset(buf.len() as int) as *const _,
buf.data() as *const _)
};
let stk = Stack::Managed {
buf: buf,
valgrind_id: valgrind_id
};
stk
Stack::Managed(platform::Stack::new(size))
}
pub unsafe fn native(limit: *const u8) -> Stack {
@ -52,43 +20,16 @@ impl Stack {
}
pub fn top(&mut self) -> *mut u8 {
unsafe {
match *self {
Stack::Native { .. } => ptr::null_mut(),
Stack::Managed { ref buf, .. } => {
buf.data().offset(buf.len() as int)
}
}
match *self {
Stack::Native { .. } => ptr::null_mut(),
Stack::Managed(ref mut stack) => stack.top()
}
}
pub fn limit(&self) -> *const u8 {
unsafe {
match *self {
Stack::Native { sp_limit, .. } => sp_limit,
Stack::Managed { ref buf, .. } => {
buf.data().offset(page_size() as int) as *const _
}
}
}
}
}
fn protect_last_page(stack: &MemoryMap) -> bool {
unsafe {
let last_page = stack.data() as *mut libc::c_void;
libc::mprotect(last_page, page_size() as libc::size_t,
libc::PROT_NONE) != -1
}
}
impl Drop for Stack {
fn drop(&mut self) {
match *self {
Stack::Native { .. } => {},
Stack::Managed { valgrind_id, .. } => unsafe {
platform::stack_deregister(valgrind_id);
}
Stack::Native { sp_limit, .. } => sp_limit,
Stack::Managed(ref stack) => stack.limit()
}
}
}