@@ -221,7 +221,7 @@ mod imp {
221
221
PTHREAD_CREATE_JOINABLE ) , 0 ) ;
222
222
223
223
// 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 ) ;
225
225
match pthread_attr_setstacksize ( & mut attr, stack_size as libc:: size_t ) {
226
226
0 => {
227
227
} ,
@@ -261,51 +261,40 @@ mod imp {
261
261
#[ cfg( not( target_os = "macos" ) , not( target_os = "android" ) ) ]
262
262
pub unsafe fn yield_now ( ) { assert_eq ! ( pthread_yield( ) , 0 ) ; }
263
263
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
-
269
264
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
270
265
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
271
266
// storage. We need that information to avoid blowing up when a small stack
272
267
// is created in an application with big thread-local storage requirements.
273
268
// See #6233 for rationale and details.
274
269
//
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!
292
274
#[ 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 ) ,
305
287
}
306
288
}
307
289
}
308
290
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
+
309
298
extern {
310
299
fn pthread_create ( native : * mut libc:: pthread_t ,
311
300
attr : * libc:: pthread_attr_t ,
0 commit comments