1+ use super :: lazy:: LazyKeyInner ;
2+ use crate :: cell:: Cell ;
3+ use crate :: sys:: thread_local_dtor:: register_dtor;
4+ use crate :: { fmt, mem, panic} ;
5+
16#[ doc( hidden) ]
2- #[ macro_export]
3- #[ allow_internal_unstable(
4- thread_local_internals,
5- cfg_target_thread_local,
6- thread_local,
7- libstd_thread_internals
8- ) ]
7+ #[ allow_internal_unstable( thread_local_internals, cfg_target_thread_local, thread_local) ]
98#[ allow_internal_unsafe]
10- macro_rules! __thread_local_inner {
9+ #[ unstable( feature = "thread_local_internals" , issue = "none" ) ]
10+ #[ rustc_macro_transparency = "semitransparent" ]
11+ pub macro thread_local_inner {
1112 // used to generate the `LocalKey` value for const-initialized thread locals
1213 ( @key $t: ty, const $init: expr) => { {
1314 #[ cfg_attr( not( bootstrap) , inline) ]
@@ -49,7 +50,7 @@ macro_rules! __thread_local_inner {
4950 // 0 == we haven't registered a destructor, so do
5051 // so now.
5152 0 => {
52- $crate:: thread:: __LocalKeyInner :: <$t>:: register_dtor(
53+ $crate:: thread:: local_impl :: Key :: < $t> :: register_dtor (
5354 $crate:: ptr:: addr_of_mut!( VAL ) as * mut $crate:: primitive:: u8 ,
5455 destroy,
5556 ) ;
@@ -69,7 +70,7 @@ macro_rules! __thread_local_inner {
6970 unsafe {
7071 $crate:: thread:: LocalKey :: new ( __getit)
7172 }
72- } } ;
73+ } } ,
7374
7475 // used to generate the `LocalKey` value for `thread_local!`
7576 ( @key $t: ty, $init: expr) => {
@@ -82,8 +83,8 @@ macro_rules! __thread_local_inner {
8283 init : $crate:: option:: Option < & mut $crate:: option:: Option < $t> > ,
8384 ) -> $crate:: option:: Option < & ' static $t> {
8485 #[ thread_local]
85- static __KEY: $crate:: thread:: __LocalKeyInner <$t> =
86- $crate:: thread:: __LocalKeyInner :: <$t>:: new( ) ;
86+ static __KEY: $crate:: thread:: local_impl :: Key < $t> =
87+ $crate:: thread:: local_impl :: Key :: < $t> :: new ( ) ;
8788
8889 // FIXME: remove the #[allow(...)] marker when macros don't
8990 // raise warning for missing/extraneous unsafe blocks anymore.
@@ -107,148 +108,140 @@ macro_rules! __thread_local_inner {
107108 $crate:: thread:: LocalKey :: new ( __getit)
108109 }
109110 }
110- } ;
111+ } ,
111112 ( $( #[ $attr: meta] ) * $vis: vis $name: ident, $t: ty, $( $init: tt) * ) => {
112113 $( #[ $attr] ) * $vis const $name: $crate:: thread:: LocalKey <$t> =
113- $crate:: __thread_local_inner !( @key $t, $( $init) * ) ;
114- }
114+ $crate:: thread :: local_impl :: thread_local_inner !( @key $t, $( $init) * ) ;
115+ } ,
115116}
116117
117- #[ doc( hidden) ]
118- pub mod fast {
119- use super :: super :: lazy:: LazyKeyInner ;
120- use crate :: cell:: Cell ;
121- use crate :: sys:: thread_local_dtor:: register_dtor;
122- use crate :: { fmt, mem, panic} ;
123-
124- #[ derive( Copy , Clone ) ]
125- enum DtorState {
126- Unregistered ,
127- Registered ,
128- RunningOrHasRun ,
129- }
118+ #[ derive ( Copy , Clone ) ]
119+ enum DtorState {
120+ Unregistered ,
121+ Registered ,
122+ RunningOrHasRun ,
123+ }
130124
131- // This data structure has been carefully constructed so that the fast path
132- // only contains one branch on x86. That optimization is necessary to avoid
133- // duplicated tls lookups on OSX.
125+ // This data structure has been carefully constructed so that the fast path
126+ // only contains one branch on x86. That optimization is necessary to avoid
127+ // duplicated tls lookups on OSX.
128+ //
129+ // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
130+ pub struct Key <T > {
131+ // If `LazyKeyInner::get` returns `None`, that indicates either:
132+ // * The value has never been initialized
133+ // * The value is being recursively initialized
134+ // * The value has already been destroyed or is being destroyed
135+ // To determine which kind of `None`, check `dtor_state`.
134136 //
135- // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
136- pub struct Key < T > {
137- // If `LazyKeyInner::get` returns `None`, that indicates either:
138- // * The value has never been initialized
139- // * The value is being recursively initialized
140- // * The value has already been destroyed or is being destroyed
141- // To determine which kind of `None`, check `dtor_state`.
142- //
143- // This is very optimizer friendly for the fast path - initialized but
144- // not yet dropped.
145- inner : LazyKeyInner < T > ,
137+ // This is very optimizer friendly for the fast path - initialized but
138+ // not yet dropped.
139+ inner: LazyKeyInner <T >,
146140
147- // Metadata to keep track of the state of the destructor. Remember that
148- // this variable is thread-local, not global.
149- dtor_state : Cell < DtorState > ,
150- }
141+ // Metadata to keep track of the state of the destructor. Remember that
142+ // this variable is thread-local, not global.
143+ dtor_state: Cell <DtorState >,
144+ }
151145
152- impl < T > fmt:: Debug for Key < T > {
153- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
154- f. debug_struct ( "Key" ) . finish_non_exhaustive ( )
155- }
146+ impl<T > fmt:: Debug for Key <T > {
147+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
148+ f. debug_struct ( "Key" ) . finish_non_exhaustive ( )
156149 }
150+ }
157151
158- impl < T > Key < T > {
159- pub const fn new ( ) -> Key < T > {
160- Key { inner : LazyKeyInner :: new ( ) , dtor_state : Cell :: new ( DtorState :: Unregistered ) }
161- }
152+ impl < T > Key < T > {
153+ pub const fn new ( ) -> Key < T > {
154+ Key { inner : LazyKeyInner :: new ( ) , dtor_state : Cell :: new ( DtorState :: Unregistered ) }
155+ }
162156
163- // note that this is just a publicly-callable function only for the
164- // const-initialized form of thread locals, basically a way to call the
165- // free `register_dtor` function defined elsewhere in std.
166- pub unsafe fn register_dtor ( a : * mut u8 , dtor : unsafe extern "C" fn ( * mut u8 ) ) {
167- unsafe {
168- register_dtor ( a, dtor) ;
169- }
157+ // note that this is just a publicly-callable function only for the
158+ // const-initialized form of thread locals, basically a way to call the
159+ // free `register_dtor` function defined elsewhere in std.
160+ pub unsafe fn register_dtor ( a : * mut u8 , dtor : unsafe extern "C" fn ( * mut u8 ) ) {
161+ unsafe {
162+ register_dtor ( a, dtor) ;
170163 }
164+ }
171165
172- pub unsafe fn get < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
173- // SAFETY: See the definitions of `LazyKeyInner::get` and
174- // `try_initialize` for more information.
175- //
176- // The caller must ensure no mutable references are ever active to
177- // the inner cell or the inner T when this is called.
178- // The `try_initialize` is dependant on the passed `init` function
179- // for this.
180- unsafe {
181- match self . inner . get ( ) {
182- Some ( val) => Some ( val) ,
183- None => self . try_initialize ( init) ,
184- }
166+ pub unsafe fn get < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
167+ // SAFETY: See the definitions of `LazyKeyInner::get` and
168+ // `try_initialize` for more information.
169+ //
170+ // The caller must ensure no mutable references are ever active to
171+ // the inner cell or the inner T when this is called.
172+ // The `try_initialize` is dependant on the passed `init` function
173+ // for this.
174+ unsafe {
175+ match self . inner . get ( ) {
176+ Some ( val) => Some ( val) ,
177+ None => self . try_initialize ( init) ,
185178 }
186179 }
180+ }
187181
188- // `try_initialize` is only called once per fast thread local variable,
189- // except in corner cases where thread_local dtors reference other
190- // thread_local's, or it is being recursively initialized.
191- //
192- // Macos: Inlining this function can cause two `tlv_get_addr` calls to
193- // be performed for every call to `Key::get`.
194- // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
195- #[ inline( never) ]
196- unsafe fn try_initialize < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
182+ // `try_initialize` is only called once per fast thread local variable,
183+ // except in corner cases where thread_local dtors reference other
184+ // thread_local's, or it is being recursively initialized.
185+ //
186+ // Macos: Inlining this function can cause two `tlv_get_addr` calls to
187+ // be performed for every call to `Key::get`.
188+ // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
189+ #[ inline( never) ]
190+ unsafe fn try_initialize < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
191+ // SAFETY: See comment above (this function doc).
192+ if !mem:: needs_drop :: < T > ( ) || unsafe { self . try_register_dtor ( ) } {
197193 // SAFETY: See comment above (this function doc).
198- if !mem:: needs_drop :: < T > ( ) || unsafe { self . try_register_dtor ( ) } {
199- // SAFETY: See comment above (this function doc).
200- Some ( unsafe { self . inner . initialize ( init) } )
201- } else {
202- None
203- }
194+ Some ( unsafe { self . inner . initialize ( init) } )
195+ } else {
196+ None
204197 }
198+ }
205199
206- // `try_register_dtor` is only called once per fast thread local
207- // variable, except in corner cases where thread_local dtors reference
208- // other thread_local's, or it is being recursively initialized.
209- unsafe fn try_register_dtor ( & self ) -> bool {
210- match self . dtor_state . get ( ) {
211- DtorState :: Unregistered => {
212- // SAFETY: dtor registration happens before initialization.
213- // Passing `self` as a pointer while using `destroy_value<T>`
214- // is safe because the function will build a pointer to a
215- // Key<T>, which is the type of self and so find the correct
216- // size.
217- unsafe { register_dtor ( self as * const _ as * mut u8 , destroy_value :: < T > ) } ;
218- self . dtor_state . set ( DtorState :: Registered ) ;
219- true
220- }
221- DtorState :: Registered => {
222- // recursively initialized
223- true
224- }
225- DtorState :: RunningOrHasRun => false ,
200+ // `try_register_dtor` is only called once per fast thread local
201+ // variable, except in corner cases where thread_local dtors reference
202+ // other thread_local's, or it is being recursively initialized.
203+ unsafe fn try_register_dtor ( & self ) -> bool {
204+ match self . dtor_state . get ( ) {
205+ DtorState :: Unregistered => {
206+ // SAFETY: dtor registration happens before initialization.
207+ // Passing `self` as a pointer while using `destroy_value<T>`
208+ // is safe because the function will build a pointer to a
209+ // Key<T>, which is the type of self and so find the correct
210+ // size.
211+ unsafe { register_dtor ( self as * const _ as * mut u8 , destroy_value :: < T > ) } ;
212+ self . dtor_state . set ( DtorState :: Registered ) ;
213+ true
226214 }
215+ DtorState :: Registered => {
216+ // recursively initialized
217+ true
218+ }
219+ DtorState :: RunningOrHasRun => false ,
227220 }
228221 }
222+ }
229223
230- unsafe extern "C" fn destroy_value < T > ( ptr : * mut u8 ) {
231- let ptr = ptr as * mut Key < T > ;
224+ unsafe extern "C" fn destroy_value < T > ( ptr : * mut u8 ) {
225+ let ptr = ptr as * mut Key < T > ;
232226
233- // SAFETY:
234- //
235- // The pointer `ptr` has been built just above and comes from
236- // `try_register_dtor` where it is originally a Key<T> coming from `self`,
237- // making it non-NUL and of the correct type.
238- //
239- // Right before we run the user destructor be sure to set the
240- // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
241- // causes future calls to `get` to run `try_initialize_drop` again,
242- // which will now fail, and return `None`.
243- //
244- // Wrap the call in a catch to ensure unwinding is caught in the event
245- // a panic takes place in a destructor.
246- if let Err ( _) = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || unsafe {
247- let value = ( * ptr) . inner . take ( ) ;
248- ( * ptr) . dtor_state . set ( DtorState :: RunningOrHasRun ) ;
249- drop ( value) ;
250- } ) ) {
251- rtabort ! ( "thread local panicked on drop" ) ;
252- }
227+ // SAFETY:
228+ //
229+ // The pointer `ptr` has been built just above and comes from
230+ // `try_register_dtor` where it is originally a Key<T> coming from `self`,
231+ // making it non-NUL and of the correct type.
232+ //
233+ // Right before we run the user destructor be sure to set the
234+ // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
235+ // causes future calls to `get` to run `try_initialize_drop` again,
236+ // which will now fail, and return `None`.
237+ //
238+ // Wrap the call in a catch to ensure unwinding is caught in the event
239+ // a panic takes place in a destructor.
240+ if let Err ( _) = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || unsafe {
241+ let value = ( * ptr) . inner . take ( ) ;
242+ ( * ptr) . dtor_state . set ( DtorState :: RunningOrHasRun ) ;
243+ drop ( value) ;
244+ } ) ) {
245+ rtabort ! ( "thread local panicked on drop" ) ;
253246 }
254247}
0 commit comments