1use super::{Thread, ThreadId};
2use crate::mem::ManuallyDrop;
3use crate::ptr;
4use crate::sys::thread_local::local_pointer;
56const NONE: *mut () = ptr::null_mut();
7const BUSY: *mut () = ptr::without_provenance_mut(1);
8const DESTROYED: *mut () = ptr::without_provenance_mut(2);
910local_pointer! {
11static CURRENT;
12}
1314/// Persistent storage for the thread ID.
15///
16/// We store the thread ID so that it never gets destroyed during the lifetime
17/// of a thread, either using `#[thread_local]` or multiple `local_pointer!`s.
18pub(super) mod id {
19use super::*;
2021cfg_if::cfg_if! {
22if #[cfg(target_thread_local)] {
23use crate::cell::Cell;
2425#[thread_local]
26static ID: Cell<Option<ThreadId>> = Cell::new(None);
2728pub(super) const CHEAP: bool = true;
2930pub(crate) fn get() -> Option<ThreadId> {
31 ID.get()
32 }
3334pub(super) fn set(id: ThreadId) {
35 ID.set(Some(id))
36 }
37 } else if #[cfg(target_pointer_width = "16")] {
38local_pointer! {
39static ID0;
40static ID16;
41static ID32;
42static ID48;
43 }
4445pub(super) const CHEAP: bool = false;
4647pub(crate) fn get() -> Option<ThreadId> {
48let id0 = ID0.get().addr() as u64;
49let id16 = ID16.get().addr() as u64;
50let id32 = ID32.get().addr() as u64;
51let id48 = ID48.get().addr() as u64;
52 ThreadId::from_u64((id48 << 48) + (id32 << 32) + (id16 << 16) + id0)
53 }
5455pub(super) fn set(id: ThreadId) {
56let val = id.as_u64().get();
57 ID0.set(ptr::without_provenance_mut(val as usize));
58 ID16.set(ptr::without_provenance_mut((val >> 16) as usize));
59 ID32.set(ptr::without_provenance_mut((val >> 32) as usize));
60 ID48.set(ptr::without_provenance_mut((val >> 48) as usize));
61 }
62 } else if #[cfg(target_pointer_width = "32")] {
63local_pointer! {
64static ID0;
65static ID32;
66 }
6768pub(super) const CHEAP: bool = false;
6970pub(crate) fn get() -> Option<ThreadId> {
71let id0 = ID0.get().addr() as u64;
72let id32 = ID32.get().addr() as u64;
73 ThreadId::from_u64((id32 << 32) + id0)
74 }
7576pub(super) fn set(id: ThreadId) {
77let val = id.as_u64().get();
78 ID0.set(ptr::without_provenance_mut(val as usize));
79 ID32.set(ptr::without_provenance_mut((val >> 32) as usize));
80 }
81 } else {
82local_pointer! {
83static ID;
84 }
8586pub(super) const CHEAP: bool = true;
8788pub(crate) fn get() -> Option<ThreadId> {
89let id = ID.get().addr() as u64;
90 ThreadId::from_u64(id)
91 }
9293pub(super) fn set(id: ThreadId) {
94let val = id.as_u64().get();
95 ID.set(ptr::without_provenance_mut(val as usize));
96 }
97 }
98 }
99100#[inline]
101pub(super) fn get_or_init() -> ThreadId {
102 get().unwrap_or_else(
103#[cold]
104|| {
105let id = ThreadId::new();
106 id::set(id);
107 id
108 },
109 )
110 }
111}
112113/// Tries to set the thread handle for the current thread. Fails if a handle was
114/// already set or if the thread ID of `thread` would change an already-set ID.
115pub(super) fn set_current(thread: Thread) -> Result<(), Thread> {
116if CURRENT.get() != NONE {
117return Err(thread);
118 }
119120match id::get() {
121Some(id) if id == thread.id() => {}
122None => id::set(thread.id()),
123_ => return Err(thread),
124 }
125126// Make sure that `crate::rt::thread_cleanup` will be run, which will
127 // call `drop_current`.
128crate::sys::thread_local::guard::enable();
129 CURRENT.set(thread.into_raw().cast_mut());
130Ok(())
131}
132133/// Gets the id of the thread that invokes it.
134///
135/// This function will always succeed, will always return the same value for
136/// one thread and is guaranteed not to call the global allocator.
137#[inline]
138pub(crate) fn current_id() -> ThreadId {
139// If accessing the persistent thread ID takes multiple TLS accesses, try
140 // to retrieve it from the current thread handle, which will only take one
141 // TLS access.
142if !id::CHEAP {
143if let Some(id) = try_with_current(|t| t.map(|t| t.id())) {
144return id;
145 }
146 }
147148 id::get_or_init()
149}
150151/// Gets a reference to the handle of the thread that invokes it, if the handle
152/// has been initialized.
153pub(super) fn try_with_current<F, R>(f: F) -> R
154where
155F: FnOnce(Option<&Thread>) -> R,
156{
157let current = CURRENT.get();
158if current > DESTROYED {
159// SAFETY: `Arc` does not contain interior mutability, so it does not
160 // matter that the address of the handle might be different depending
161 // on where this is called.
162unsafe {
163let current = ManuallyDrop::new(Thread::from_raw(current));
164 f(Some(¤t))
165 }
166 } else {
167 f(None)
168 }
169}
170171/// Gets a handle to the thread that invokes it. If the handle stored in thread-
172/// local storage was already destroyed, this creates a new unnamed temporary
173/// handle to allow thread parking in nearly all situations.
174pub(crate) fn current_or_unnamed() -> Thread {
175let current = CURRENT.get();
176if current > DESTROYED {
177unsafe {
178let current = ManuallyDrop::new(Thread::from_raw(current));
179 (*current).clone()
180 }
181 } else if current == DESTROYED {
182 Thread::new(id::get_or_init(), None)
183 } else {
184 init_current(current)
185 }
186}
187188/// Gets a handle to the thread that invokes it.
189///
190/// # Examples
191///
192/// Getting a handle to the current thread with `thread::current()`:
193///
194/// ```
195/// use std::thread;
196///
197/// let handler = thread::Builder::new()
198/// .name("named thread".into())
199/// .spawn(|| {
200/// let handle = thread::current();
201/// assert_eq!(handle.name(), Some("named thread"));
202/// })
203/// .unwrap();
204///
205/// handler.join().unwrap();
206/// ```
207#[must_use]
208#[stable(feature = "rust1", since = "1.0.0")]
209pub fn current() -> Thread {
210let current = CURRENT.get();
211if current > DESTROYED {
212unsafe {
213let current = ManuallyDrop::new(Thread::from_raw(current));
214 (*current).clone()
215 }
216 } else {
217 init_current(current)
218 }
219}
220221#[cold]
222fn init_current(current: *mut ()) -> Thread {
223if current == NONE {
224 CURRENT.set(BUSY);
225// If the thread ID was initialized already, use it.
226let id = id::get_or_init();
227let thread = Thread::new(id, None);
228229// Make sure that `crate::rt::thread_cleanup` will be run, which will
230 // call `drop_current`.
231crate::sys::thread_local::guard::enable();
232 CURRENT.set(thread.clone().into_raw().cast_mut());
233 thread
234 } else if current == BUSY {
235// BUSY exists solely for this check, but as it is in the slow path, the
236 // extra TLS write above shouldn't matter. The alternative is nearly always
237 // a stack overflow.
238239 // If you came across this message, contact the author of your allocator.
240 // If you are said author: A surprising amount of functions inside the
241 // standard library (e.g. `Mutex`, `thread_local!`, `File` when using long
242 // paths, even `panic!` when using unwinding), need memory allocation, so
243 // you'll get circular dependencies all over the place when using them.
244 // I (joboet) highly recommend using only APIs from core in your allocator
245 // and implementing your own system abstractions. Still, if you feel that
246 // a particular API should be entirely allocation-free, feel free to open
247 // an issue on the Rust repository, we'll see what we can do.
248rtabort!(
249"\n\
250 Attempted to access thread-local data while allocating said data.\n\
251 Do not access functions that allocate in the global allocator!\n\
252 This is a bug in the global allocator.\n\
253 "
254)
255 } else {
256debug_assert_eq!(current, DESTROYED);
257panic!(
258"use of std::thread::current() is not possible after the thread's \
259 local data has been destroyed"
260)
261 }
262}
263264/// This should be run in [`crate::rt::thread_cleanup`] to reset the thread
265/// handle.
266pub(crate) fn drop_current() {
267let current = CURRENT.get();
268if current > DESTROYED {
269unsafe {
270 CURRENT.set(DESTROYED);
271 drop(Thread::from_raw(current));
272 }
273 }
274}