1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
use super::lazy::LazyKeyInner;
use crate::cell::Cell;
use crate::sys::thread_local_dtor::register_dtor;
use crate::{fmt, mem, panic};
#[doc(hidden)]
#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
#[allow_internal_unsafe]
#[unstable(feature = "thread_local_internals", issue = "none")]
#[rustc_macro_transparency = "semitransparent"]
pub macro thread_local_inner {
// 用于为常量初始化的线程局部变量生成 `LocalKey` 值
(@key $t:ty, const $init:expr) => {{
#[inline]
#[deny(unsafe_op_in_unsafe_fn)]
unsafe fn __getit(
_init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
const INIT_EXPR: $t = $init;
// 如果平台支持 `#[thread_local]`,请使用它。
#[thread_local]
static mut VAL: $t = INIT_EXPR;
// 如果不需要 dtor,我们可以做一些 "非常原始" 的事情,然后开始。
//
if !$crate::mem::needs_drop::<$t>() {
unsafe {
return $crate::option::Option::Some(&VAL)
}
}
// 0 == dtor 未注册
// 1 == dtor 已注册,dtor 未运行
// 2 == dtor 已注册并正在运行或已运行
#[thread_local]
static mut STATE: $crate::primitive::u8 = 0;
unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
let ptr = ptr as *mut $t;
unsafe {
$crate::debug_assert_eq!(STATE, 1);
STATE = 2;
$crate::ptr::drop_in_place(ptr);
}
}
unsafe {
match STATE {
// 0 == 我们还没有注册析构函数,所以现在注册。
//
0 => {
$crate::thread::local_impl::Key::<$t>::register_dtor(
$crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
destroy,
);
STATE = 1;
$crate::option::Option::Some(&VAL)
}
// 1 == 析构函数已注册且值有效,因此返回指针。
//
1 => $crate::option::Option::Some(&VAL),
// 否则析构函数已经运行,所以我们不能授予访问权限。
//
_ => $crate::option::Option::None,
}
}
}
unsafe {
$crate::thread::LocalKey::new(__getit)
}
}},
// 用于为 `thread_local!` 生成 `LocalKey` 值
(@key $t:ty, $init:expr) => {
{
#[inline]
fn __init() -> $t { $init }
#[inline]
unsafe fn __getit(
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
#[thread_local]
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::<$t>::new();
// FIXME: 当宏不再对丢失/额外不安全块发出警告时,请删除 #[allow(...)] 标记。
// See https://github.com/rust-lang/rust/issues/74838.
//
#[allow(unused_unsafe)]
unsafe {
__KEY.get(move || {
if let $crate::option::Option::Some(init) = init {
if let $crate::option::Option::Some(value) = init.take() {
return value;
} else if $crate::cfg!(debug_assertions) {
$crate::unreachable!("missing default value");
}
}
__init()
})
}
}
unsafe {
$crate::thread::LocalKey::new(__getit)
}
}
},
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
},
}
#[derive(Copy, Clone)]
enum DtorState {
Unregistered,
Registered,
RunningOrHasRun,
}
// 此数据结构体经过精心构造,因此快速路径仅包含 x86 上的一个分支。
// 为了避免在 OSX 上重复查找 tls,必须进行优化。
//
// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
//
pub struct Key<T> {
// 如果 `LazyKeyInner::get` 返回 `None`,则表明:
// * 该值从未初始化
// * 该值正在递归初始化
// * 该值已被销毁或正在被销毁。要确定哪种 `None`,请检查 `dtor_state`。
//
//
// 这对快速路径非常优化,它非常友好 - 已初始化但尚未丢弃。
//
inner: LazyKeyInner<T>,
// 跟踪析构函数状态的元数据。
// 请记住,此变量是线程局部的,而不是局部的。
dtor_state: Cell<DtorState>,
}
impl<T> fmt::Debug for Key<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Key").finish_non_exhaustive()
}
}
impl<T> Key<T> {
pub const fn new() -> Key<T> {
Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
}
// 请注意,这只是一个可公开调用的函数,仅适用于线程局部变量的 const 初始化形式,基本上是一种调用 std 中其他地方定义的免费 `register_dtor` 函数的方法。
//
//
pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
unsafe {
register_dtor(a, dtor);
}
}
pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
// SAFETY: 有关详细信息,请参见 `LazyKeyInner::get` 和 `try_initialize` 的定义。
//
// 调用者必须确保在调用此内部 cell 或内部 T 时永远不会对它起作用。
//
// `try_initialize` 为此而依赖于传递的 `init` 函数。
//
//
unsafe {
match self.inner.get() {
Some(val) => Some(val),
None => self.try_initialize(init),
}
}
}
// 每个快速线程局部变量只调用一次 `try_initialize`,除非在 thread_local dtor 引用其他 thread_local 的极端情况下,或者它正在被递归初始化。
//
//
// Macos: 内联这个函数会导致每个调用到 `Key::get` 时执行两次 `tlv_get_addr` 调用。
// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
//
//
#[inline(never)]
unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
// SAFETY: 请参见上面的注释 (此函数文档)。
if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } {
// SAFETY: 请参见上面的注释 (此函数文档)。
Some(unsafe { self.inner.initialize(init) })
} else {
None
}
}
// 每个快速线程局部变量只调用一次 `try_register_dtor`,除非在 thread_local dtor 引用其他 thread_local 的极端情况下,或者它正在被递归初始化。
//
//
unsafe fn try_register_dtor(&self) -> bool {
match self.dtor_state.get() {
DtorState::Unregistered => {
// SAFETY: dtor 注册发生在初始化之前。
// 使用 `destroy_value<T>` 时将 `self` 作为指针传递是安全的,因为函数将建立指向 Key<T> 的指针,Key<T> 是 self 的类型,因此可以找到正确的大小。
//
//
//
unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) };
self.dtor_state.set(DtorState::Registered);
true
}
DtorState::Registered => {
// 递归初始化
true
}
DtorState::RunningOrHasRun => false,
}
}
}
unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
let ptr = ptr as *mut Key<T>;
// SAFETY:
//
// 指针 `ptr` 刚好在上面构建,并且来自 `try_register_dtor`,它最初是 `self` 的 Key<T>,使其成为非 NUL 且类型正确。
//
//
// 在运行用户析构函数之前,请确保将 `Option<T>` 设置为 `None`,将 `dtor_state` 设置为 `RunningOrHasRun`。
// 这将导致对 `get` 的 future 调用再次运行 `try_initialize_drop`,该操作现在将失败,并返回 `None`。
//
// 将调用包裹在一个 catch 中,以确保在析构函数中发生 panic 时捕获展开。
//
//
//
//
if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
let value = (*ptr).inner.take();
(*ptr).dtor_state.set(DtorState::RunningOrHasRun);
drop(value);
})) {
rtabort!("thread local panicked on drop");
}
}