diff options
| author | Ben Noordhuis <info@bnoordhuis.nl> | 2014-01-29 18:19:23 +0100 |
|---|---|---|
| committer | Ben Noordhuis <info@bnoordhuis.nl> | 2014-01-31 13:47:25 +0100 |
| commit | 431edacbef23e691d1b192da78b4112c35addfbf (patch) | |
| tree | 2bd5f9664b3b572ac447b18deef2a931950fed54 /src/libstd/rt | |
| parent | b02b5cdcf42b4fe6b1e3ebe56ad0cd43fd907489 (diff) | |
| download | rust-431edacbef23e691d1b192da78b4112c35addfbf.tar.gz rust-431edacbef23e691d1b192da78b4112c35addfbf.zip | |
Use __pthread_get_minstack() when available.
glibc >= 2.15 has a __pthread_get_minstack() function that returns PTHREAD_STACK_MIN plus however many bytes are needed for thread-local storage. Use it when it's available because just PTHREAD_STACK_MIN is not enough in applications that have big thread-local storage requirements. Fixes #6233.
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/thread.rs | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs index 605923ac99c..b762c1173f5 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_STACK_MIN as uint); + let stack_size = cmp::max(stack, RED_ZONE + __pthread_get_minstack(&attr) as uint); match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) { 0 => { }, @@ -261,6 +261,51 @@ 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), + } + } + } + } + extern { fn pthread_create(native: *mut libc::pthread_t, attr: *libc::pthread_attr_t, |
