diff --git a/src/lib.rs b/src/lib.rs index 038c394..0ffff79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,4 @@ #![feature(default_type_params, macro_rules)] -extern crate libc; extern crate fn_box; pub use context::Context; diff --git a/src/platform.rs b/src/platform.rs index 5754c78..9e15e0f 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -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 _ + } + } } diff --git a/src/stack.rs b/src/stack.rs index 01de813..18bfbd5 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -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() } } }