about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/common/mod.rs5
-rw-r--r--src/libstd/sys/common/stack.rs311
-rw-r--r--src/libstd/sys/common/thread.rs7
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs72
-rw-r--r--src/libstd/sys/unix/thread.rs5
-rw-r--r--src/libstd/sys/windows/c.rs25
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs102
-rw-r--r--src/libstd/sys/windows/thread.rs11
8 files changed, 85 insertions, 453 deletions
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index b205b6df4cb..d63b66c42c7 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -21,7 +21,6 @@ pub mod io;
 pub mod poison;
 pub mod remutex;
 pub mod rwlock;
-pub mod stack;
 pub mod thread;
 pub mod thread_info;
 pub mod thread_local;
@@ -52,3 +51,7 @@ pub trait IntoInner<Inner> {
 pub trait FromInner<Inner> {
     fn from_inner(inner: Inner) -> Self;
 }
+
+#[cfg(stage0)]
+#[lang = "stack_exhausted"]
+pub fn stack_exhausted() {}
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
deleted file mode 100644
index 41c8ac4aed3..00000000000
--- a/src/libstd/sys/common/stack.rs
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Rust stack-limit management
-//!
-//! Currently Rust uses a segmented-stack-like scheme in order to detect stack
-//! overflow for rust threads. In this scheme, the prologue of all functions are
-//! preceded with a check to see whether the current stack limits are being
-//! exceeded.
-//!
-//! This module provides the functionality necessary in order to manage these
-//! stack limits (which are stored in platform-specific locations). The
-//! functions here are used at the borders of the thread lifetime in order to
-//! manage these limits.
-//!
-//! This function is an unstable module because this scheme for stack overflow
-//! detection is not guaranteed to continue in the future. Usage of this module
-//! is discouraged unless absolutely necessary.
-
-// iOS related notes
-//
-// It is possible to implement it using idea from
-// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
-//
-// In short: _pthread_{get,set}_specific_direct allows extremely fast
-// access, exactly what is required for segmented stack
-// There is a pool of reserved slots for Apple internal use (0..119)
-// First dynamic allocated pthread key starts with 257 (on iOS7)
-// So using slot 149 should be pretty safe ASSUMING space is reserved
-// for every key < first dynamic key
-//
-// There is also an opportunity to steal keys reserved for Garbage Collection
-// ranges 80..89 and 110..119, especially considering the fact Garbage Collection
-// never supposed to work on iOS. But as everybody knows it - there is a chance
-// that those slots will be re-used, like it happened with key 95 (moved from
-// JavaScriptCore to CoreText)
-//
-// Unfortunately Apple rejected patch to LLVM which generated
-// corresponding prolog, decision was taken to disable segmented
-// stack support on iOS.
-
-pub const RED_ZONE: usize = 20 * 1024;
-
-/// This function is invoked from rust's current __morestack function. Segmented
-/// stacks are currently not enabled as segmented stacks, but rather one giant
-/// stack segment. This means that whenever we run out of stack, we want to
-/// truly consider it to be stack overflow rather than allocating a new stack.
-#[cfg(not(test))] // in testing, use the original libstd's version
-#[lang = "stack_exhausted"]
-extern fn stack_exhausted() {
-    use intrinsics;
-
-    unsafe {
-        // We're calling this function because the stack just ran out. We need
-        // to call some other rust functions, but if we invoke the functions
-        // right now it'll just trigger this handler being called again. In
-        // order to alleviate this, we move the stack limit to be inside of the
-        // red zone that was allocated for exactly this reason.
-        let limit = get_sp_limit();
-        record_sp_limit(limit - RED_ZONE / 2);
-
-        // This probably isn't the best course of action. Ideally one would want
-        // to unwind the stack here instead of just aborting the entire process.
-        // This is a tricky problem, however. There's a few things which need to
-        // be considered:
-        //
-        //  1. We're here because of a stack overflow, yet unwinding will run
-        //     destructors and hence arbitrary code. What if that code overflows
-        //     the stack? One possibility is to use the above allocation of an
-        //     extra 10k to hope that we don't hit the limit, and if we do then
-        //     abort the whole program. Not the best, but kind of hard to deal
-        //     with unless we want to switch stacks.
-        //
-        //  2. LLVM will optimize functions based on whether they can unwind or
-        //     not. It will flag functions with 'nounwind' if it believes that
-        //     the function cannot trigger unwinding, but if we do unwind on
-        //     stack overflow then it means that we could unwind in any function
-        //     anywhere. We would have to make sure that LLVM only places the
-        //     nounwind flag on functions which don't call any other functions.
-        //
-        //  3. The function that overflowed may have owned arguments. These
-        //     arguments need to have their destructors run, but we haven't even
-        //     begun executing the function yet, so unwinding will not run the
-        //     any landing pads for these functions. If this is ignored, then
-        //     the arguments will just be leaked.
-        //
-        // Exactly what to do here is a very delicate topic, and is possibly
-        // still up in the air for what exactly to do. Some relevant issues:
-        //
-        //  #3555 - out-of-stack failure leaks arguments
-        //  #3695 - should there be a stack limit?
-        //  #9855 - possible strategies which could be taken
-        //  #9854 - unwinding on windows through __morestack has never worked
-        //  #2361 - possible implementation of not using landing pads
-
-        ::rt::util::report_overflow();
-
-        intrinsics::abort();
-    }
-}
-
-// Windows maintains a record of upper and lower stack bounds in the Thread Information
-// Block (TIB), and some syscalls do check that addresses which are supposed to be in
-// the stack, indeed lie between these two values.
-// (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839)
-//
-// When using Rust-managed stacks (libgreen), we must maintain these values accordingly.
-// For OS-managed stacks (libnative), we let the OS manage them for us.
-//
-// On all other platforms both variants behave identically.
-
-#[inline(always)]
-pub unsafe fn record_os_managed_stack_bounds(stack_lo: usize, _stack_hi: usize) {
-    record_sp_limit(stack_lo + RED_ZONE);
-}
-
-/// Records the current limit of the stack as specified by `end`.
-///
-/// This is stored in an OS-dependent location, likely inside of the thread
-/// local storage. The location that the limit is stored is a pre-ordained
-/// location because it's where LLVM has emitted code to check.
-///
-/// Note that this cannot be called under normal circumstances. This function is
-/// changing the stack limit, so upon returning any further function calls will
-/// possibly be triggering the morestack logic if you're not careful.
-///
-/// Also note that this and all of the inside functions are all flagged as
-/// "inline(always)" because they're messing around with the stack limits.  This
-/// would be unfortunate for the functions themselves to trigger a morestack
-/// invocation (if they were an actual function call).
-#[inline(always)]
-pub unsafe fn record_sp_limit(limit: usize) {
-    return target_record_sp_limit(limit);
-
-    #[cfg(all(target_arch = "x86_64",
-              any(target_os = "macos", target_os = "ios")))]
-    #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        asm!("movq $$0x60+90*8, %rsi
-              movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile")
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile")
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)]
-    unsafe fn target_record_sp_limit(_: usize) {
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile")
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))]
-    #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile")
-    }
-
-    #[cfg(all(target_arch = "x86",
-              any(target_os = "macos", target_os = "ios")))]
-    #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        asm!("movl $$0x48+90*4, %eax
-              movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
-    }
-    #[cfg(all(target_arch = "x86", target_os = "linux"))]
-    #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
-    }
-    #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)]
-    unsafe fn target_record_sp_limit(_: usize) {
-    }
-
-    // mips, arm - The implementations are a bit big for inline asm!
-    //             They can be found in src/rt/arch/$target_arch/record_sp.S
-    #[cfg(any(target_arch = "mips",
-              target_arch = "mipsel",
-              all(target_arch = "arm", not(target_os = "ios"))))]
-    #[inline(always)]
-    unsafe fn target_record_sp_limit(limit: usize) {
-        use libc::c_void;
-        return record_sp_limit(limit as *const c_void);
-        extern {
-            fn record_sp_limit(limit: *const c_void);
-        }
-    }
-
-    // aarch64 - FIXME(AARCH64): missing...
-    // powerpc - FIXME(POWERPC): missing...
-    // arm-ios - iOS segmented stack is disabled for now, see related notes
-    // openbsd/bitrig/netbsd - no segmented stacks.
-    // x86-freebsd - no segmented stacks.
-    #[cfg(any(target_arch = "aarch64",
-              target_arch = "powerpc",
-              all(target_arch = "arm", target_os = "ios"),
-              all(target_arch = "x86", target_os = "freebsd"),
-              target_os = "bitrig",
-              target_os = "netbsd",
-              target_os = "openbsd"))]
-    unsafe fn target_record_sp_limit(_: usize) {
-    }
-}
-
-/// The counterpart of the function above, this function will fetch the current
-/// stack limit stored in TLS.
-///
-/// Note that all of these functions are meant to be exact counterparts of their
-/// brethren above, except that the operands are reversed.
-///
-/// As with the setter, this function does not have a __morestack header and can
-/// therefore be called in a "we're out of stack" situation.
-#[inline(always)]
-pub unsafe fn get_sp_limit() -> usize {
-    return target_get_sp_limit();
-
-    #[cfg(all(target_arch = "x86_64",
-              any(target_os = "macos", target_os = "ios")))]
-    #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        let limit;
-        asm!("movq $$0x60+90*8, %rsi
-              movq %gs:(%rsi), $0" : "=r"(limit) :: "rsi" : "volatile");
-        return limit;
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        let limit;
-        asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile");
-        return limit;
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        return 1024;
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        let limit;
-        asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile");
-        return limit;
-    }
-    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))]
-    #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        let limit;
-        asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile");
-        return limit;
-    }
-
-    #[cfg(all(target_arch = "x86",
-              any(target_os = "macos", target_os = "ios")))]
-    #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        let limit;
-        asm!("movl $$0x48+90*4, %eax
-              movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile");
-        return limit;
-    }
-    #[cfg(all(target_arch = "x86", target_os = "linux"))]
-    #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        let limit;
-        asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile");
-        return limit;
-    }
-    #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        return 1024;
-    }
-
-    // mips, arm - The implementations are a bit big for inline asm!
-    //             They can be found in src/rt/arch/$target_arch/record_sp.S
-    #[cfg(any(target_arch = "mips",
-              target_arch = "mipsel",
-              all(target_arch = "arm", not(target_os = "ios"))))]
-    #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        use libc::c_void;
-        return get_sp_limit() as usize;
-        extern {
-            fn get_sp_limit() -> *const c_void;
-        }
-    }
-
-    // aarch64 - FIXME(AARCH64): missing...
-    // powerpc - FIXME(POWERPC): missing...
-    // arm-ios - no segmented stacks.
-    // openbsd/bitrig/netbsd - no segmented stacks.
-    // x86-freebsd - no segmented stacks..
-    //
-    // This function might be called by runtime though
-    // so it is unsafe to unreachable, let's return a fixed constant.
-    #[cfg(any(target_arch = "aarch64",
-              target_arch = "powerpc",
-              all(target_arch = "arm", target_os = "ios"),
-              all(target_arch = "x86", target_os = "freebsd"),
-              target_os = "bitrig",
-              target_os = "netbsd",
-              target_os = "openbsd"))]
-    #[inline(always)]
-    unsafe fn target_get_sp_limit() -> usize {
-        1024
-    }
-}
diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs
index d19ef11c01f..16f4f01bf39 100644
--- a/src/libstd/sys/common/thread.rs
+++ b/src/libstd/sys/common/thread.rs
@@ -13,15 +13,8 @@ use prelude::v1::*;
 use alloc::boxed::FnBox;
 use libc;
 use sys::stack_overflow;
-use sys_common::stack;
-use usize;
 
-#[no_stack_check]
 pub unsafe fn start_thread(main: *mut libc::c_void) {
-    // First ensure that we don't trigger __morestack (also why this has a
-    // no_stack_check annotation).
-    stack::record_os_managed_stack_bounds(0, usize::MAX);
-
     // Next, set up our stack overflow handler which may get triggered if we run
     // out of stack.
     let _handler = stack_overflow::Handler::new();
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index ed4e50735a6..4e4cf2b0ed1 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -40,25 +40,17 @@ impl Drop for Handler {
           target_os = "netbsd",
           target_os = "openbsd"))]
 mod imp {
-    use sys_common::stack;
-
     use super::Handler;
     use rt::util::report_overflow;
     use mem;
     use ptr;
-    use intrinsics;
     use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL,
                  SA_SIGINFO, SA_ONSTACK, sigaltstack,
-                 SIGSTKSZ, sighandler_t, raise};
+                 SIGSTKSZ, sighandler_t};
     use libc;
     use libc::funcs::posix88::mman::{mmap, munmap};
-    use libc::funcs::posix01::signal::signal;
-    use libc::consts::os::posix88::{SIGSEGV,
-                                    PROT_READ,
-                                    PROT_WRITE,
-                                    MAP_PRIVATE,
-                                    MAP_ANON,
-                                    MAP_FAILED};
+    use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON};
+    use libc::MAP_FAILED;
 
     use sys_common::thread_info;
 
@@ -66,46 +58,48 @@ mod imp {
     // This is initialized in init() and only read from after
     static mut PAGE_SIZE: usize = 0;
 
-    #[no_stack_check]
+    // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
+    // (unmapped pages) at the end of every thread's stack, so if a thread ends
+    // up running into the guard page it'll trigger this handler. We want to
+    // detect these cases and print out a helpful error saying that the stack
+    // has overflowed. All other signals, however, should go back to what they
+    // were originally supposed to do.
+    //
+    // This handler currently exists purely to print an informative message
+    // whenever a thread overflows its stack. When run the handler always
+    // un-registers itself after running and then returns (to allow the original
+    // signal to be delivered again). By returning we're ensuring that segfaults
+    // do indeed look like segfaults.
+    //
+    // Returning from this kind of signal handler is technically not defined to
+    // work when reading the POSIX spec strictly, but in practice it turns out
+    // many large systems and all implementations allow returning from a signal
+    // handler to work. For a more detailed explanation see the comments on
+    // #26458.
     unsafe extern fn signal_handler(signum: libc::c_int,
-                                     info: *mut siginfo,
-                                     _data: *mut libc::c_void) {
-
-        // We can not return from a SIGSEGV or SIGBUS signal.
-        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html
-
-        unsafe fn term(signum: libc::c_int) -> ! {
-            use core::mem::transmute;
-
-            signal(signum, transmute(SIG_DFL));
-            raise(signum);
-            intrinsics::abort();
-        }
-
-        // We're calling into functions with stack checks
-        stack::record_sp_limit(0);
-
+                                    info: *mut siginfo,
+                                    _data: *mut libc::c_void) {
         let guard = thread_info::stack_guard().unwrap_or(0);
         let addr = (*info).si_addr as usize;
 
-        if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
-            term(signum);
+        // If the faulting address is within the guard page, then we print a
+        // message saying so.
+        if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard {
+            report_overflow();
         }
 
-        report_overflow();
+        // Unregister ourselves by reverting back to the default behavior.
+        let mut action: sigaction = mem::zeroed();
+        action.sa_sigaction = SIG_DFL;
+        sigaction(signum, &action, ptr::null_mut());
 
-        intrinsics::abort()
+        // See comment above for why this function returns.
     }
 
     static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;
 
     pub unsafe fn init() {
-        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
-        if psize == -1 {
-            panic!("failed to get page size");
-        }
-
-        PAGE_SIZE = psize as usize;
+        PAGE_SIZE = ::sys::os::page_size();
 
         let mut action: sigaction = mem::zeroed();
         action.sa_flags = SA_SIGINFO | SA_ONSTACK;
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 67ecd4d9229..ea1bfbd9b7d 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -23,7 +23,6 @@ use ptr;
 use sys::os;
 use time::Duration;
 
-use sys_common::stack::RED_ZONE;
 use sys_common::thread::*;
 
 pub struct Thread {
@@ -43,8 +42,7 @@ impl Thread {
         let mut attr: libc::pthread_attr_t = mem::zeroed();
         assert_eq!(pthread_attr_init(&mut attr), 0);
 
-        // Reserve room for the red zone, the runtime's stack of last resort.
-        let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr));
+        let stack_size = cmp::max(stack, min_stack_size(&attr));
         match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
             0 => {}
             n => {
@@ -72,7 +70,6 @@ impl Thread {
             Ok(Thread { id: native })
         };
 
-        #[no_stack_check]
         extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
             unsafe { start_thread(main); }
             0 as *mut _
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 06c14b39e12..8fb03ae7902 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -78,6 +78,10 @@ pub const PROGRESS_QUIET: libc::DWORD = 3;
 pub const TOKEN_ADJUST_PRIVILEGES: libc::DWORD = 0x0020;
 pub const SE_PRIVILEGE_ENABLED: libc::DWORD = 2;
 
+pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
+pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
+pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -327,6 +331,24 @@ pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
     pub ReparseTarget: libc::WCHAR,
 }
 
+#[repr(C)]
+pub struct EXCEPTION_RECORD {
+    pub ExceptionCode: DWORD,
+    pub ExceptionFlags: DWORD,
+    pub ExceptionRecord: *mut EXCEPTION_RECORD,
+    pub ExceptionAddress: LPVOID,
+    pub NumberParameters: DWORD,
+    pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
+}
+
+#[repr(C)]
+pub struct EXCEPTION_POINTERS {
+    pub ExceptionRecord: *mut EXCEPTION_RECORD,
+    pub ContextRecord: LPVOID
+}
+
+pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
+        fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
 
 #[link(name = "ws2_32")]
 #[link(name = "userenv")]
@@ -487,6 +509,9 @@ extern "system" {
                                  BufferLength: libc::DWORD,
                                  PreviousState: PTOKEN_PRIVILEGES,
                                  ReturnLength: *mut libc::DWORD) -> libc::BOOL;
+    pub fn AddVectoredExceptionHandler(FirstHandler: ULONG,
+                                       VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
+                                       -> LPVOID;
 }
 
 // Functions that aren't available on Windows XP, but we still use them and just
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
index bc8ee6619f1..f93f7c756de 100644
--- a/src/libstd/sys/windows/stack_overflow.rs
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -8,108 +8,44 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[cfg(stage0)]
-use core::prelude::v1::*;
-
-use libc::types::os::arch::extra::{LPVOID, DWORD, LONG};
-use libc;
-use mem;
-use ptr;
+use libc::{self, LONG};
 use rt::util::report_overflow;
 use sys::c;
-use sys_common::stack;
 
-pub struct Handler {
-    _data: *mut libc::c_void
-}
+pub struct Handler;
 
 impl Handler {
     pub unsafe fn new() -> Handler {
-        make_handler()
+        // This API isn't available on XP, so don't panic in that case and just
+        // pray it works out ok.
+        if c::SetThreadStackGuarantee(&mut 0x5000) == 0 {
+            if libc::GetLastError() as u32 != libc::ERROR_CALL_NOT_IMPLEMENTED as u32 {
+                panic!("failed to reserve stack space for exception handling");
+            }
+        }
+        Handler
     }
 }
 
-impl Drop for Handler {
-    fn drop(&mut self) {}
-}
-
-// This is initialized in init() and only read from after
-static mut PAGE_SIZE: usize = 0;
-
-#[no_stack_check]
-extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
+extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS)
+                                    -> LONG {
     unsafe {
         let rec = &(*(*ExceptionInfo).ExceptionRecord);
         let code = rec.ExceptionCode;
 
-        if code != EXCEPTION_STACK_OVERFLOW {
-            return EXCEPTION_CONTINUE_SEARCH;
+        if code == c::EXCEPTION_STACK_OVERFLOW {
+            report_overflow();
         }
-
-        // We're calling into functions with stack checks,
-        // however stack checks by limit should be disabled on Windows
-        stack::record_sp_limit(0);
-
-        report_overflow();
-
-        EXCEPTION_CONTINUE_SEARCH
+        c::EXCEPTION_CONTINUE_SEARCH
     }
 }
 
 pub unsafe fn init() {
-    let mut info = mem::zeroed();
-    libc::GetSystemInfo(&mut info);
-    PAGE_SIZE = info.dwPageSize as usize;
-
-    if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
+    if c::AddVectoredExceptionHandler(0, vectored_handler).is_null() {
         panic!("failed to install exception handler");
     }
-
-    mem::forget(make_handler());
-}
-
-pub unsafe fn cleanup() {
-}
-
-pub unsafe fn make_handler() -> Handler {
-    // This API isn't available on XP, so don't panic in that case and just pray
-    // it works out ok.
-    if c::SetThreadStackGuarantee(&mut 0x5000) == 0 {
-        if libc::GetLastError() as u32 != libc::ERROR_CALL_NOT_IMPLEMENTED as u32 {
-            panic!("failed to reserve stack space for exception handling");
-        }
-    }
-
-    Handler { _data: 0 as *mut libc::c_void }
-}
-
-#[repr(C)]
-pub struct EXCEPTION_RECORD {
-    pub ExceptionCode: DWORD,
-    pub ExceptionFlags: DWORD,
-    pub ExceptionRecord: *mut EXCEPTION_RECORD,
-    pub ExceptionAddress: LPVOID,
-    pub NumberParameters: DWORD,
-    pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
+    // Set the thread stack guarantee for the main thread.
+    let _h = Handler::new();
 }
 
-#[repr(C)]
-pub struct EXCEPTION_POINTERS {
-    pub ExceptionRecord: *mut EXCEPTION_RECORD,
-    pub ContextRecord: LPVOID
-}
-
-pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
-        fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
-
-pub type ULONG = libc::c_ulong;
-
-const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
-const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
-const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
-
-extern "system" {
-    fn AddVectoredExceptionHandler(FirstHandler: ULONG,
-                                   VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
-                                  -> LPVOID;
-}
+pub unsafe fn cleanup() {}
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 15df5d756be..a9d094375b2 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -11,14 +11,12 @@
 use prelude::v1::*;
 
 use alloc::boxed::FnBox;
-use cmp;
 use io;
 use libc::{self, c_void, DWORD};
 use mem;
 use ptr;
 use sys::c;
 use sys::handle::Handle;
-use sys_common::stack::RED_ZONE;
 use sys_common::thread::*;
 use time::Duration;
 
@@ -36,11 +34,9 @@ impl Thread {
         // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
         // just that below a certain threshold you can't do anything useful.
         // That threshold is application and architecture-specific, however.
-        // For now, the only requirement is that it's big enough to hold the
-        // red zone.  Round up to the next 64 kB because that's what the NT
-        // kernel does, might as well make it explicit.  With the current
-        // 20 kB red zone, that makes for a 64 kB minimum stack.
-        let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
+        // Round up to the next 64 kB because that's what the NT kernel does,
+        // might as well make it explicit.
+        let stack_size = (stack + 0xfffe) & (!0xfffe);
         let ret = c::CreateThread(ptr::null_mut(), stack_size as libc::size_t,
                                   thread_start, &*p as *const _ as *mut _,
                                   0, ptr::null_mut());
@@ -52,7 +48,6 @@ impl Thread {
             Ok(Thread { handle: Handle::new(ret) })
         };
 
-        #[no_stack_check]
         extern "system" fn thread_start(main: *mut libc::c_void) -> DWORD {
             unsafe { start_thread(main); }
             0