mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
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.
This commit is contained in:
parent
b02b5cdcf4
commit
431edacbef
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user