diff options
| author | Chris Denton <christophersdenton@gmail.com> | 2024-03-16 18:27:34 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-16 18:27:34 +0000 |
| commit | a9f8f8b070db99a476393c1a9444a2860d67ca83 (patch) | |
| tree | c75ae3d04dda3934a4dfa054b1a2d946c777a0c9 | |
| parent | 42e03fc158e21818c23f0b155b3d1336507ae3db (diff) | |
| parent | b0b249399a97e7f3ac97996f26993bf67fc9bfba (diff) | |
| download | rust-a9f8f8b070db99a476393c1a9444a2860d67ca83.tar.gz rust-a9f8f8b070db99a476393c1a9444a2860d67ca83.zip | |
Rollup merge of #122583 - Zoxc:tls-non-mut, r=joboet
Use `UnsafeCell` for fast constant thread locals This uses `UnsafeCell` instead of `static mut` for fast constant thread locals. This changes the type of the TLS shims to return `&UnsafeCell<T>` instead of `*mut T` which means they are always non-null so LLVM can optimize away the check for `Some` in `LocalKey::with` if `T` has no destructor. LLVM is currently unable to do this optimization as we lose the fact that `__getit` always returns `Some` as it gets optimized to just returning the value of the TLS shim.
| -rw-r--r-- | library/std/src/sys/thread_local/fast_local.rs | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/library/std/src/sys/thread_local/fast_local.rs b/library/std/src/sys/thread_local/fast_local.rs index 646dcd7f3a3..69ee70de30c 100644 --- a/library/std/src/sys/thread_local/fast_local.rs +++ b/library/std/src/sys/thread_local/fast_local.rs @@ -13,22 +13,21 @@ pub macro thread_local_inner { (@key $t:ty, const $init:expr) => {{ #[inline] #[deny(unsafe_op_in_unsafe_fn)] - // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint - #[cfg_attr(bootstrap, allow(static_mut_ref))] - #[cfg_attr(not(bootstrap), allow(static_mut_refs))] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { const INIT_EXPR: $t = $init; // If the platform has support for `#[thread_local]`, use it. #[thread_local] - static mut VAL: $t = INIT_EXPR; + // We use `UnsafeCell` here instead of `static mut` to ensure any generated TLS shims + // have a nonnull attribute on their return value. + static VAL: $crate::cell::UnsafeCell<$t> = $crate::cell::UnsafeCell::new(INIT_EXPR); // If a dtor isn't needed we can do something "very raw" and // just get going. if !$crate::mem::needs_drop::<$t>() { unsafe { - return $crate::option::Option::Some(&VAL) + return $crate::option::Option::Some(&*VAL.get()) } } @@ -55,15 +54,15 @@ pub macro thread_local_inner { // so now. 0 => { $crate::thread::local_impl::Key::<$t>::register_dtor( - $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8, + VAL.get() as *mut $crate::primitive::u8, destroy, ); STATE.set(1); - $crate::option::Option::Some(&VAL) + $crate::option::Option::Some(&*VAL.get()) } // 1 == the destructor is registered and the value // is valid, so return the pointer. - 1 => $crate::option::Option::Some(&VAL), + 1 => $crate::option::Option::Some(&*VAL.get()), // otherwise the destructor has already run, so we // can't give access. _ => $crate::option::Option::None, |
