@@ -166,8 +166,8 @@ macro_rules! __thread_local_inner {
166
166
{
167
167
#[ thread_local]
168
168
#[ cfg( target_thread_local) ]
169
- static __KEY: $crate:: thread:: __ElfLocalKeyInner <$t> =
170
- $crate:: thread:: __ElfLocalKeyInner :: new( ) ;
169
+ static __KEY: $crate:: thread:: __FastLocalKeyInner <$t> =
170
+ $crate:: thread:: __FastLocalKeyInner :: new( ) ;
171
171
172
172
#[ cfg( not( target_thread_local) ) ]
173
173
static __KEY: $crate:: thread:: __OsLocalKeyInner<$t> =
@@ -310,165 +310,6 @@ impl<T: 'static> LocalKey<T> {
310
310
}
311
311
}
312
312
313
- #[ cfg( target_thread_local) ]
314
- #[ doc( hidden) ]
315
- pub mod elf {
316
- use cell:: { Cell , UnsafeCell } ;
317
- use intrinsics;
318
- use ptr;
319
-
320
- pub struct Key < T > {
321
- inner : UnsafeCell < Option < T > > ,
322
-
323
- // Metadata to keep track of the state of the destructor. Remember that
324
- // these variables are thread-local, not global.
325
- dtor_registered : Cell < bool > ,
326
- dtor_running : Cell < bool > ,
327
- }
328
-
329
- unsafe impl < T > :: marker:: Sync for Key < T > { }
330
-
331
- impl < T > Key < T > {
332
- pub const fn new ( ) -> Key < T > {
333
- Key {
334
- inner : UnsafeCell :: new ( None ) ,
335
- dtor_registered : Cell :: new ( false ) ,
336
- dtor_running : Cell :: new ( false )
337
- }
338
- }
339
-
340
- pub fn get ( & ' static self ) -> Option < & ' static UnsafeCell < Option < T > > > {
341
- unsafe {
342
- if intrinsics:: needs_drop :: < T > ( ) && self . dtor_running . get ( ) {
343
- return None
344
- }
345
- self . register_dtor ( ) ;
346
- }
347
- Some ( & self . inner )
348
- }
349
-
350
- unsafe fn register_dtor ( & self ) {
351
- if !intrinsics:: needs_drop :: < T > ( ) || self . dtor_registered . get ( ) {
352
- return
353
- }
354
-
355
- register_dtor ( self as * const _ as * mut u8 ,
356
- destroy_value :: < T > ) ;
357
- self . dtor_registered . set ( true ) ;
358
- }
359
- }
360
-
361
- #[ cfg( any( target_os = "linux" , target_os = "fuchsia" ) ) ]
362
- unsafe fn register_dtor_fallback ( t : * mut u8 , dtor : unsafe extern fn ( * mut u8 ) ) {
363
- // The fallback implementation uses a vanilla OS-based TLS key to track
364
- // the list of destructors that need to be run for this thread. The key
365
- // then has its own destructor which runs all the other destructors.
366
- //
367
- // The destructor for DTORS is a little special in that it has a `while`
368
- // loop to continuously drain the list of registered destructors. It
369
- // *should* be the case that this loop always terminates because we
370
- // provide the guarantee that a TLS key cannot be set after it is
371
- // flagged for destruction.
372
- use sys_common:: thread_local as os;
373
-
374
- static DTORS : os:: StaticKey = os:: StaticKey :: new ( Some ( run_dtors) ) ;
375
- type List = Vec < ( * mut u8 , unsafe extern fn ( * mut u8 ) ) > ;
376
- if DTORS . get ( ) . is_null ( ) {
377
- let v: Box < List > = box Vec :: new ( ) ;
378
- DTORS . set ( Box :: into_raw ( v) as * mut u8 ) ;
379
- }
380
- let list: & mut List = & mut * ( DTORS . get ( ) as * mut List ) ;
381
- list. push ( ( t, dtor) ) ;
382
-
383
- unsafe extern fn run_dtors ( mut ptr : * mut u8 ) {
384
- while !ptr. is_null ( ) {
385
- let list: Box < List > = Box :: from_raw ( ptr as * mut List ) ;
386
- for & ( ptr, dtor) in list. iter ( ) {
387
- dtor ( ptr) ;
388
- }
389
- ptr = DTORS . get ( ) ;
390
- DTORS . set ( ptr:: null_mut ( ) ) ;
391
- }
392
- }
393
- }
394
-
395
- // Since what appears to be glibc 2.18 this symbol has been shipped which
396
- // GCC and clang both use to invoke destructors in thread_local globals, so
397
- // let's do the same!
398
- //
399
- // Note, however, that we run on lots older linuxes, as well as cross
400
- // compiling from a newer linux to an older linux, so we also have a
401
- // fallback implementation to use as well.
402
- //
403
- // Due to rust-lang/rust#18804, make sure this is not generic!
404
- #[ cfg( target_os = "linux" ) ]
405
- unsafe fn register_dtor ( t : * mut u8 , dtor : unsafe extern fn ( * mut u8 ) ) {
406
- use mem;
407
- use libc;
408
-
409
- extern {
410
- #[ linkage = "extern_weak" ]
411
- static __dso_handle: * mut u8 ;
412
- #[ linkage = "extern_weak" ]
413
- static __cxa_thread_atexit_impl: * const libc:: c_void ;
414
- }
415
- if !__cxa_thread_atexit_impl. is_null ( ) {
416
- type F = unsafe extern fn ( dtor : unsafe extern fn ( * mut u8 ) ,
417
- arg : * mut u8 ,
418
- dso_handle : * mut u8 ) -> libc:: c_int ;
419
- mem:: transmute :: < * const libc:: c_void , F > ( __cxa_thread_atexit_impl)
420
- ( dtor, t, & __dso_handle as * const _ as * mut _ ) ;
421
- return
422
- }
423
- register_dtor_fallback ( t, dtor) ;
424
- }
425
-
426
- // OSX's analog of the above linux function is this _tlv_atexit function.
427
- // The disassembly of thread_local globals in C++ (at least produced by
428
- // clang) will have this show up in the output.
429
- #[ cfg( target_os = "macos" ) ]
430
- unsafe fn register_dtor ( t : * mut u8 , dtor : unsafe extern fn ( * mut u8 ) ) {
431
- extern {
432
- fn _tlv_atexit ( dtor : unsafe extern fn ( * mut u8 ) ,
433
- arg : * mut u8 ) ;
434
- }
435
- _tlv_atexit ( dtor, t) ;
436
- }
437
-
438
- // Just use the thread_local fallback implementation, at least until there's
439
- // a more direct implementation.
440
- #[ cfg( target_os = "fuchsia" ) ]
441
- unsafe fn register_dtor ( t : * mut u8 , dtor : unsafe extern fn ( * mut u8 ) ) {
442
- register_dtor_fallback ( t, dtor) ;
443
- }
444
-
445
- pub unsafe extern fn destroy_value < T > ( ptr : * mut u8 ) {
446
- let ptr = ptr as * mut Key < T > ;
447
- // Right before we run the user destructor be sure to flag the
448
- // destructor as running for this thread so calls to `get` will return
449
- // `None`.
450
- ( * ptr) . dtor_running . set ( true ) ;
451
-
452
- // The OSX implementation of TLS apparently had an odd aspect to it
453
- // where the pointer we have may be overwritten while this destructor
454
- // is running. Specifically if a TLS destructor re-accesses TLS it may
455
- // trigger a re-initialization of all TLS variables, paving over at
456
- // least some destroyed ones with initial values.
457
- //
458
- // This means that if we drop a TLS value in place on OSX that we could
459
- // revert the value to its original state halfway through the
460
- // destructor, which would be bad!
461
- //
462
- // Hence, we use `ptr::read` on OSX (to move to a "safe" location)
463
- // instead of drop_in_place.
464
- if cfg ! ( target_os = "macos" ) {
465
- ptr:: read ( ( * ptr) . inner . get ( ) ) ;
466
- } else {
467
- ptr:: drop_in_place ( ( * ptr) . inner . get ( ) ) ;
468
- }
469
- }
470
- }
471
-
472
313
#[ doc( hidden) ]
473
314
pub mod os {
474
315
use cell:: { Cell , UnsafeCell } ;
0 commit comments