Use UnsafeCell for fast constant thread locals

This commit is contained in:
John Kåre Alsaker 2024-03-16 06:00:05 +01:00
parent c5b571310d
commit b0b249399a

View File

@ -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,