@@ -166,8 +166,8 @@ macro_rules! __thread_local_inner {
166166 {
167167 #[ thread_local]
168168 #[ 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( ) ;
171171
172172 #[ cfg( not( target_thread_local) ) ]
173173 static __KEY: $crate:: thread:: __OsLocalKeyInner<$t> =
@@ -310,165 +310,6 @@ impl<T: 'static> LocalKey<T> {
310310 }
311311}
312312
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-
472313#[ doc( hidden) ]
473314pub mod os {
474315 use cell:: { Cell , UnsafeCell } ;
0 commit comments