Skip to content

Commit ffb7d35

Browse files
committed
Link weakly to __pthread_get_minstack().
Use the weak symbol support that was added in the previous commit to link weakly against __pthread_get_minstack(). Significantly reduces the thread creation overhead because Thread::imp::create() no longer goes through a dlopen/dlsym/dlcose cycle for each new thread.
1 parent 57d65da commit ffb7d35

File tree

2 files changed

+32
-36
lines changed

2 files changed

+32
-36
lines changed

src/libstd/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@
5252
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
5353
html_root_url = "http://static.rust-lang.org/doc/master")];
5454

55-
#[feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args, simd)];
55+
#[feature(asm,
56+
globs,
57+
link_args,
58+
linkage,
59+
macro_rules,
60+
managed_boxes,
61+
simd,
62+
thread_local)];
5663

5764
// Don't link to std. We are std.
5865
#[no_std];

src/libstd/rt/thread.rs

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ mod imp {
221221
PTHREAD_CREATE_JOINABLE), 0);
222222

223223
// Reserve room for the red zone, the runtime's stack of last resort.
224-
let stack_size = cmp::max(stack, RED_ZONE + __pthread_get_minstack(&attr) as uint);
224+
let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
225225
match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
226226
0 => {
227227
},
@@ -261,51 +261,40 @@ mod imp {
261261
#[cfg(not(target_os = "macos"), not(target_os = "android"))]
262262
pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }
263263

264-
#[cfg(not(target_os = "linux"))]
265-
unsafe fn __pthread_get_minstack(_: *libc::pthread_attr_t) -> libc::size_t {
266-
libc::PTHREAD_STACK_MIN
267-
}
268-
269264
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
270265
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
271266
// storage. We need that information to avoid blowing up when a small stack
272267
// is created in an application with big thread-local storage requirements.
273268
// See #6233 for rationale and details.
274269
//
275-
// Dynamically resolve the symbol for compatibility with older versions
276-
// of glibc. Assumes that we've been dynamically linked to libpthread
277-
// but that is currently always the case. Note that this means we take
278-
// a dlopen/dlsym/dlclose hit for every new thread. Mitigating that by
279-
// caching the symbol or the function's return value has its drawbacks:
280-
//
281-
// * Caching the symbol breaks when libpthread.so is reloaded because
282-
// its address changes.
283-
//
284-
// * Caching the return value assumes that it's a fixed quantity.
285-
// Not very future-proof and untrue in the presence of guard pages
286-
// The reason __pthread_get_minstack() takes a *libc::pthread_attr_t
287-
// as its argument is because it takes pthread_attr_setguardsize() into
288-
// account.
289-
//
290-
// A better solution is to define __pthread_get_minstack() as a weak symbol
291-
// but there is currently no way to express that in Rust code.
270+
// Link weakly to the symbol for compatibility with older versions of glibc.
271+
// Assumes that we've been dynamically linked to libpthread but that is
272+
// currently always the case. Note that you need to check that the symbol
273+
// is non-null before calling it!
292274
#[cfg(target_os = "linux")]
293-
unsafe fn __pthread_get_minstack(attr: *libc::pthread_attr_t) -> libc::size_t {
294-
use option::None;
295-
use result::{Err, Ok};
296-
use unstable::dynamic_lib;
297-
match dynamic_lib::DynamicLibrary::open(None) {
298-
Err(err) => fail!("DynamicLibrary::open(): {}", err),
299-
Ok(handle) => {
300-
match handle.symbol::<extern "C" fn(*libc::pthread_attr_t) ->
301-
libc::size_t>("__pthread_get_minstack") {
302-
Err(_) => libc::PTHREAD_STACK_MIN,
303-
Ok(__pthread_get_minstack) => __pthread_get_minstack(attr),
304-
}
275+
fn min_stack_size(attr: *libc::pthread_attr_t) -> libc::size_t {
276+
extern {
277+
#[linkage = "extern_weak"]
278+
fn __pthread_get_minstack(_: *libc::pthread_attr_t) -> libc::size_t;
279+
}
280+
unsafe fn is_null<T>(thing: T) -> bool {
281+
cast::transmute::<T, *u8>(thing) == ptr::null()
282+
}
283+
unsafe {
284+
match is_null(__pthread_get_minstack) {
285+
true => PTHREAD_STACK_MIN,
286+
false => __pthread_get_minstack(attr),
305287
}
306288
}
307289
}
308290

291+
// __pthread_get_minstack() is marked as weak but extern_weak linkage is
292+
// not supported on OS X, hence this kludge...
293+
#[cfg(not(target_os = "linux"))]
294+
fn min_stack_size(_: *libc::pthread_attr_t) -> libc::size_t {
295+
PTHREAD_STACK_MIN
296+
}
297+
309298
extern {
310299
fn pthread_create(native: *mut libc::pthread_t,
311300
attr: *libc::pthread_attr_t,

0 commit comments

Comments
 (0)