about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstd/rt/mod.rs4
-rw-r--r--src/libstd/sys/common/thread_info.rs8
-rw-r--r--src/libstd/sys/unix/thread.rs88
-rw-r--r--src/libstd/sys/windows/thread.rs7
4 files changed, 60 insertions, 47 deletions
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 1729d20da20..0ac0d03e19d 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -96,7 +96,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
         // own fault handlers if we hit it.
         sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom,
                                                           my_stack_top);
-        sys::thread::guard::init();
+        let main_guard = sys::thread::guard::init();
         sys::stack_overflow::init();
 
         // Next, set up the current Thread with the guard information we just
@@ -104,7 +104,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
         // but we just do this to name the main thread and to give it correct
         // info about the stack bounds.
         let thread: Thread = NewThread::new(Some("<main>".to_string()));
-        thread_info::set(sys::thread::guard::main(), thread);
+        thread_info::set(main_guard, thread);
 
         // By default, some platforms will send a *signal* when a EPIPE error
         // would otherwise be delivered. This runtime doesn't install a SIGPIPE
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
index ae55bae37aa..bb47c946e49 100644
--- a/src/libstd/sys/common/thread_info.rs
+++ b/src/libstd/sys/common/thread_info.rs
@@ -18,7 +18,7 @@ use thread::Thread;
 use thread::LocalKeyState;
 
 struct ThreadInfo {
-    stack_guard: usize,
+    stack_guard: Option<usize>,
     thread: Thread,
 }
 
@@ -33,7 +33,7 @@ impl ThreadInfo {
         THREAD_INFO.with(move |c| {
             if c.borrow().is_none() {
                 *c.borrow_mut() = Some(ThreadInfo {
-                    stack_guard: 0,
+                    stack_guard: None,
                     thread: NewThread::new(None),
                 })
             }
@@ -47,10 +47,10 @@ pub fn current_thread() -> Option<Thread> {
 }
 
 pub fn stack_guard() -> Option<usize> {
-    ThreadInfo::with(|info| info.stack_guard)
+    ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
 }
 
-pub fn set(stack_guard: usize, thread: Thread) {
+pub fn set(stack_guard: Option<usize>, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
         stack_guard: stack_guard,
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 17804c8d81f..6be61f06926 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -166,9 +166,10 @@ impl Drop for Thread {
           not(target_os = "netbsd"),
           not(target_os = "openbsd")))]
 pub mod guard {
-    pub unsafe fn current() -> usize { 0 }
-    pub unsafe fn main() -> usize { 0 }
-    pub unsafe fn init() {}
+    use prelude::v1::*;
+
+    pub unsafe fn current() -> Option<usize> { None }
+    pub unsafe fn init() -> Option<usize> { None }
 }
 
 
@@ -179,6 +180,8 @@ pub mod guard {
           target_os = "openbsd"))]
 #[allow(unused_imports)]
 pub mod guard {
+    use prelude::v1::*;
+
     use libc::{self, pthread_t};
     use libc::funcs::posix88::mman::mmap;
     use libc::consts::os::posix88::{PROT_NONE,
@@ -191,31 +194,38 @@ pub mod guard {
     use super::{pthread_self, pthread_attr_destroy};
     use sys::os;
 
-    // These are initialized in init() and only read from after
-    static mut GUARD_PAGE: usize = 0;
-
     #[cfg(any(target_os = "macos",
               target_os = "bitrig",
               target_os = "netbsd",
               target_os = "openbsd"))]
-    unsafe fn get_stack_start() -> *mut libc::c_void {
-        current() as *mut libc::c_void
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        current().map(|s| s as *mut libc::c_void)
     }
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
-    unsafe fn get_stack_start() -> *mut libc::c_void {
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        use super::pthread_attr_init;
+
+        let mut ret = None;
         let mut attr: libc::pthread_attr_t = mem::zeroed();
-        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
-        let mut stackaddr = ptr::null_mut();
-        let mut stacksize = 0;
-        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
+        assert_eq!(pthread_attr_init(&mut attr), 0);
+        if pthread_getattr_np(pthread_self(), &mut attr) == 0 {
+            let mut stackaddr = ptr::null_mut();
+            let mut stacksize = 0;
+            assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr,
+                                             &mut stacksize), 0);
+            ret = Some(stackaddr);
+        }
         assert_eq!(pthread_attr_destroy(&mut attr), 0);
-        stackaddr
+        ret
     }
 
-    pub unsafe fn init() {
+    pub unsafe fn init() -> Option<usize> {
         let psize = os::page_size();
-        let mut stackaddr = get_stack_start();
+        let mut stackaddr = match get_stack_start() {
+            Some(addr) => addr,
+            None => return None,
+        };
 
         // Ensure stackaddr is page aligned! A parent process might
         // have reset RLIMIT_STACK to be non-page aligned. The
@@ -245,25 +255,21 @@ pub mod guard {
 
         let offset = if cfg!(target_os = "linux") {2} else {1};
 
-        GUARD_PAGE = stackaddr as usize + offset * psize;
-    }
-
-    pub unsafe fn main() -> usize {
-        GUARD_PAGE
+        Some(stackaddr as usize + offset * psize)
     }
 
     #[cfg(target_os = "macos")]
-    pub unsafe fn current() -> usize {
+    pub unsafe fn current() -> Option<usize> {
         extern {
             fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void;
             fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t;
         }
-        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
-         pthread_get_stacksize_np(pthread_self())) as usize
+        Some((pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
+              pthread_get_stacksize_np(pthread_self())) as usize)
     }
 
     #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
-    pub unsafe fn current() -> usize {
+    pub unsafe fn current() -> Option<usize> {
         #[repr(C)]
         struct stack_t {
             ss_sp: *mut libc::c_void,
@@ -280,30 +286,36 @@ pub mod guard {
         assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0);
 
         let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
-        if pthread_main_np() == 1 {
+        Some(if pthread_main_np() == 1 {
             // main thread
             current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
         } else {
             // new thread
             current_stack.ss_sp as usize - current_stack.ss_size as usize
-        }
+        })
     }
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
-    pub unsafe fn current() -> usize {
+    pub unsafe fn current() -> Option<usize> {
+        use super::pthread_attr_init;
+
+        let mut ret = None;
         let mut attr: libc::pthread_attr_t = mem::zeroed();
-        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
-        let mut guardsize = 0;
-        assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
-        if guardsize == 0 {
-            panic!("there is no guard page");
+        assert_eq!(pthread_attr_init(&mut attr), 0);
+        if pthread_getattr_np(pthread_self(), &mut attr) == 0 {
+            let mut guardsize = 0;
+            assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
+            if guardsize == 0 {
+                panic!("there is no guard page");
+            }
+            let mut stackaddr = ptr::null_mut();
+            let mut size = 0;
+            assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
+
+            ret = Some(stackaddr as usize + guardsize as usize);
         }
-        let mut stackaddr = ptr::null_mut();
-        let mut size = 0;
-        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
         assert_eq!(pthread_attr_destroy(&mut attr), 0);
-
-        stackaddr as usize + guardsize as usize
+        return ret
     }
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 50dfee4ab10..42805c2ac52 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -86,7 +86,8 @@ impl Thread {
 }
 
 pub mod guard {
-    pub unsafe fn main() -> usize { 0 }
-    pub unsafe fn current() -> usize { 0 }
-    pub unsafe fn init() {}
+    use prelude::v1::*;
+
+    pub unsafe fn current() -> Option<usize> { None }
+    pub unsafe fn init() -> Option<usize> { None }
 }