about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lib.rs5
-rw-r--r--src/libstd/rt/thread.rs63
2 files changed, 28 insertions, 40 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index bdc4fc387ca..4d3d1641bd0 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -52,10 +52,9 @@
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")];
 
-#[feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args, simd)];
+#[feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
+          simd, linkage, default_type_params)];
 
-// Turn on default type parameters.
-#[feature(default_type_params)];
 // NOTE remove the following two attributes after the next snapshot.
 #[allow(unrecognized_lint)];
 #[allow(default_type_param_usage)];
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
index 7b24c94b518..e27698d7dd0 100644
--- a/src/libstd/rt/thread.rs
+++ b/src/libstd/rt/thread.rs
@@ -221,7 +221,7 @@ mod imp {
                                                PTHREAD_CREATE_JOINABLE), 0);
 
         // Reserve room for the red zone, the runtime's stack of last resort.
-        let stack_size = cmp::max(stack, RED_ZONE + __pthread_get_minstack(&attr) as uint);
+        let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
         match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
             0 => {
             },
@@ -261,51 +261,39 @@ mod imp {
     #[cfg(not(target_os = "macos"), not(target_os = "android"))]
     pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }
 
-    #[cfg(not(target_os = "linux"))]
-    unsafe fn __pthread_get_minstack(_: *libc::pthread_attr_t) -> libc::size_t {
-        libc::PTHREAD_STACK_MIN
-    }
-
     // glibc >= 2.15 has a __pthread_get_minstack() function that returns
     // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
     // storage.  We need that information to avoid blowing up when a small stack
     // is created in an application with big thread-local storage requirements.
     // See #6233 for rationale and details.
     //
-    // Dynamically resolve the symbol for compatibility with older versions
-    // of glibc.  Assumes that we've been dynamically linked to libpthread
-    // but that is currently always the case.  Note that this means we take
-    // a dlopen/dlsym/dlclose hit for every new thread.  Mitigating that by
-    // caching the symbol or the function's return value has its drawbacks:
-    //
-    //  * Caching the symbol breaks when libpthread.so is reloaded because
-    //    its address changes.
-    //
-    //  * Caching the return value assumes that it's a fixed quantity.
-    //    Not very future-proof and untrue in the presence of guard pages
-    //    The reason __pthread_get_minstack() takes a *libc::pthread_attr_t
-    //    as its argument is because it takes pthread_attr_setguardsize() into
-    //    account.
-    //
-    // A better solution is to define __pthread_get_minstack() as a weak symbol
-    // but there is currently no way to express that in Rust code.
-    #[cfg(target_os = "linux")]
-    unsafe fn __pthread_get_minstack(attr: *libc::pthread_attr_t) -> libc::size_t {
-        use option::None;
-        use result::{Err, Ok};
-        use unstable::dynamic_lib;
-        match dynamic_lib::DynamicLibrary::open(None) {
-            Err(err) => fail!("DynamicLibrary::open(): {}", err),
-            Ok(handle) => {
-                match handle.symbol::<extern "C" fn(*libc::pthread_attr_t) ->
-                                     libc::size_t>("__pthread_get_minstack") {
-                    Err(_) => libc::PTHREAD_STACK_MIN,
-                    Ok(__pthread_get_minstack) => __pthread_get_minstack(attr),
-                }
-            }
+    // Link weakly to the symbol for compatibility with older versions of glibc.
+    // Assumes that we've been dynamically linked to libpthread but that is
+    // currently always the case.  Note that you need to check that the symbol
+    // is non-null before calling it!
+    #[cfg(target_os = "linux", not(stage0))]
+    fn min_stack_size(attr: *libc::pthread_attr_t) -> libc::size_t {
+        use ptr::RawPtr;
+        type F = extern "C" unsafe fn(*libc::pthread_attr_t) -> libc::size_t;
+        extern {
+            #[linkage = "extern_weak"]
+            static __pthread_get_minstack: *();
+        }
+        if __pthread_get_minstack.is_null() {
+            PTHREAD_STACK_MIN
+        } else {
+            unsafe { cast::transmute::<*(), F>(__pthread_get_minstack)(attr) }
         }
     }
 
+    // __pthread_get_minstack() is marked as weak but extern_weak linkage is
+    // not supported on OS X, hence this kludge...
+    #[cfg(not(target_os = "linux"))]
+    #[cfg(stage0)]
+    fn min_stack_size(_: *libc::pthread_attr_t) -> libc::size_t {
+        PTHREAD_STACK_MIN
+    }
+
     extern {
         fn pthread_create(native: *mut libc::pthread_t,
                           attr: *libc::pthread_attr_t,
@@ -347,3 +335,4 @@ mod tests {
         assert_eq!(42, Thread::start_stack(1, proc () 42).join());
     }
 }
+