1use super::id::ThreadId;
2use super::main_thread;
3use super::thread::Thread;
4use crate::mem::ManuallyDrop;
5use crate::ptr;
6use crate::sys::threadas imp;
7use crate::sys::thread_local::local_pointer;
89const NONE: *mut () = ptr::null_mut();
10const BUSY: *mut () = ptr::without_provenance_mut(1);
11const DESTROYED: *mut () = ptr::without_provenance_mut(2);
1213#[thread_local]
static CURRENT: crate::sys::thread_local::LocalPointer =
crate::sys::thread_local::LocalPointer::__new();local_pointer! {
14static CURRENT;
15}1617/// Persistent storage for the thread ID.
18///
19/// We store the thread ID so that it never gets destroyed during the lifetime
20/// of a thread, either using `#[thread_local]` or multiple `local_pointer!`s.
21pub(super) mod id {
22use super::*;
2324cfg_select! {
25 target_thread_local => {
26use crate::cell::Cell;
2728#[thread_local]
29static ID: Cell<Option<ThreadId>> = Cell::new(None);
3031pub(super) const CHEAP: bool = true;
3233pub(crate) fn get() -> Option<ThreadId> {
34ID.get()
35 }
3637pub(super) fn set(id: ThreadId) {
38ID.set(Some(id))
39 }
40 }
41 target_pointer_width = "16" => {
42local_pointer! {
43static ID0;
44static ID16;
45static ID32;
46static ID48;
47 }
4849pub(super) const CHEAP: bool = false;
5051pub(crate) fn get() -> Option<ThreadId> {
52let id0 = ID0.get().addr() as u64;
53let id16 = ID16.get().addr() as u64;
54let id32 = ID32.get().addr() as u64;
55let id48 = ID48.get().addr() as u64;
56 ThreadId::from_u64((id48 << 48) + (id32 << 32) + (id16 << 16) + id0)
57 }
5859pub(super) fn set(id: ThreadId) {
60let val = id.as_u64().get();
61 ID0.set(ptr::without_provenance_mut(val as usize));
62 ID16.set(ptr::without_provenance_mut((val >> 16) as usize));
63 ID32.set(ptr::without_provenance_mut((val >> 32) as usize));
64 ID48.set(ptr::without_provenance_mut((val >> 48) as usize));
65 }
66 }
67 target_pointer_width = "32" => {
68local_pointer! {
69static ID0;
70static ID32;
71 }
7273pub(super) const CHEAP: bool = false;
7475pub(crate) fn get() -> Option<ThreadId> {
76let id0 = ID0.get().addr() as u64;
77let id32 = ID32.get().addr() as u64;
78 ThreadId::from_u64((id32 << 32) + id0)
79 }
8081pub(super) fn set(id: ThreadId) {
82let val = id.as_u64().get();
83 ID0.set(ptr::without_provenance_mut(val as usize));
84 ID32.set(ptr::without_provenance_mut((val >> 32) as usize));
85 }
86 }
87_ => {
88local_pointer! {
89static ID;
90 }
9192pub(super) const CHEAP: bool = true;
9394pub(crate) fn get() -> Option<ThreadId> {
95let id = ID.get().addr() as u64;
96 ThreadId::from_u64(id)
97 }
9899pub(super) fn set(id: ThreadId) {
100let val = id.as_u64().get();
101 ID.set(ptr::without_provenance_mut(val as usize));
102 }
103 }
104 }
105106#[inline]
107pub(super) fn get_or_init() -> ThreadId {
108get().unwrap_or_else(
109#[cold]
110|| {
111let id = ThreadId::new();
112 id::set(id);
113id114 },
115 )
116 }
117}
118119/// Tries to set the thread handle for the current thread. Fails if a handle was
120/// already set or if the thread ID of `thread` would change an already-set ID.
121pub(super) fn set_current(thread: Thread) -> Result<(), Thread> {
122if CURRENT.get() != NONE {
123return Err(thread);
124 }
125126match id::get() {
127Some(id) if id == thread.id() => {}
128None => id::set(thread.id()),
129_ => return Err(thread),
130 }
131132// Make sure that `crate::rt::thread_cleanup` will be run, which will
133 // call `drop_current`.
134crate::sys::thread_local::guard::enable();
135CURRENT.set(thread.into_raw().cast_mut());
136Ok(())
137}
138139/// Gets the unique identifier of the thread which invokes it.
140///
141/// Calling this function may be more efficient than accessing the current
142/// thread id through the current thread handle. i.e. `thread::current().id()`.
143///
144/// This function will always succeed, will always return the same value for
145/// one thread and is guaranteed not to call the global allocator.
146///
147/// # Examples
148///
149/// ```
150/// #![feature(current_thread_id)]
151///
152/// use std::thread;
153///
154/// let other_thread = thread::spawn(|| {
155/// thread::current_id()
156/// });
157///
158/// let other_thread_id = other_thread.join().unwrap();
159/// assert_ne!(thread::current_id(), other_thread_id);
160/// ```
161#[inline]
162#[must_use]
163#[unstable(feature = "current_thread_id", issue = "147194")]
164pub fn current_id() -> ThreadId {
165// If accessing the persistent thread ID takes multiple TLS accesses, try
166 // to retrieve it from the current thread handle, which will only take one
167 // TLS access.
168if !id::CHEAP {
169if let Some(id) = try_with_current(|t| t.map(|t| t.id())) {
170return id;
171 }
172 }
173174 id::get_or_init()
175}
176177/// Gets the OS thread ID of the thread that invokes it, if available. If not, return the Rust
178/// thread ID.
179///
180/// We use a `u64` to all possible platform IDs without excess `cfg`; most use `int`, some use a
181/// pointer, and Apple uses `uint64_t`. This is a "best effort" approach for diagnostics and is
182/// allowed to fall back to a non-OS ID (such as the Rust thread ID) or a non-unique ID (such as a
183/// PID) if the thread ID cannot be retrieved.
184pub(crate) fn current_os_id() -> u64 {
185 imp::current_os_id().unwrap_or_else(|| current_id().as_u64().get())
186}
187188/// Gets a reference to the handle of the thread that invokes it, if the handle
189/// has been initialized.
190fn try_with_current<F, R>(f: F) -> R
191where
192F: FnOnce(Option<&Thread>) -> R,
193{
194let current = CURRENT.get();
195if current > DESTROYED {
196// SAFETY: `Arc` does not contain interior mutability, so it does not
197 // matter that the address of the handle might be different depending
198 // on where this is called.
199unsafe {
200let current = ManuallyDrop::new(Thread::from_raw(current));
201f(Some(¤t))
202 }
203 } else {
204f(None)
205 }
206}
207208/// Run a function with the current thread's name.
209///
210/// Modulo thread local accesses, this function is safe to call from signal
211/// handlers and in similar circumstances where allocations are not possible.
212pub(crate) fn with_current_name<F, R>(f: F) -> R
213where
214F: FnOnce(Option<&str>) -> R,
215{
216try_with_current(|thread| {
217let name = if let Some(thread) = thread {
218// If there is a current thread handle, try to use the name stored
219 // there.
220thread.name()
221 } else if let Some(main) = main_thread::get()
222 && let Some(id) = id::get()
223 && id == main224 {
225// The main thread doesn't always have a thread handle, we must
226 // identify it through its ID instead. The checks are ordered so
227 // that the current ID is only loaded if it is actually needed,
228 // since loading it from TLS might need multiple expensive accesses.
229Some("main")
230 } else {
231None232 };
233234f(name)
235 })
236}
237238/// Gets a handle to the thread that invokes it. If the handle stored in thread-
239/// local storage was already destroyed, this creates a new unnamed temporary
240/// handle to allow thread parking in nearly all situations.
241pub(crate) fn current_or_unnamed() -> Thread {
242let current = CURRENT.get();
243if current > DESTROYED {
244unsafe {
245let current = ManuallyDrop::new(Thread::from_raw(current));
246 (*current).clone()
247 }
248 } else if current == DESTROYED {
249Thread::new(id::get_or_init(), None)
250 } else {
251init_current(current)
252 }
253}
254255/// Gets a handle to the thread that invokes it.
256///
257/// # Examples
258///
259/// Getting a handle to the current thread with `thread::current()`:
260///
261/// ```
262/// use std::thread;
263///
264/// let handler = thread::Builder::new()
265/// .name("named thread".into())
266/// .spawn(|| {
267/// let handle = thread::current();
268/// assert_eq!(handle.name(), Some("named thread"));
269/// })
270/// .unwrap();
271///
272/// handler.join().unwrap();
273/// ```
274#[must_use]
275#[stable(feature = "rust1", since = "1.0.0")]
276pub fn current() -> Thread {
277let current = CURRENT.get();
278if current > DESTROYED {
279unsafe {
280let current = ManuallyDrop::new(Thread::from_raw(current));
281 (*current).clone()
282 }
283 } else {
284init_current(current)
285 }
286}
287288#[cold]
289fn init_current(current: *mut ()) -> Thread {
290if current == NONE {
291CURRENT.set(BUSY);
292// If the thread ID was initialized already, use it.
293let id = id::get_or_init();
294let thread = Thread::new(id, None);
295296// Make sure that `crate::rt::thread_cleanup` will be run, which will
297 // call `drop_current`.
298crate::sys::thread_local::guard::enable();
299CURRENT.set(thread.clone().into_raw().cast_mut());
300thread301 } else if current == BUSY {
302// BUSY exists solely for this check, but as it is in the slow path, the
303 // extra TLS write above shouldn't matter. The alternative is nearly always
304 // a stack overflow.
305 //
306 // If we reach this point it means our initialization routine ended up
307 // calling current() either directly, or indirectly through the global
308 // allocator, which is a bug either way as we may not call the global
309 // allocator in current().
310{
if let Some(mut out) = crate::sys::stdio::panic_output() {
let _ =
crate::io::Write::write_fmt(&mut out,
format_args!("fatal runtime error: {0}, aborting\n",
format_args!("init_current() was re-entrant, which indicates a bug in the Rust threading implementation")));
};
crate::process::abort();
}rtabort!(
311"init_current() was re-entrant, which indicates a bug in the Rust threading implementation"
312)313 } else {
314if true {
match (¤t, &DESTROYED) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
};
};debug_assert_eq!(current, DESTROYED);
315{
::core::panicking::panic_fmt(format_args!("use of std::thread::current() is not possible after the thread\'s local data has been destroyed"));
}panic!(
316"use of std::thread::current() is not possible after the thread's \
317 local data has been destroyed"
318)319 }
320}
321322/// This should be run in [`crate::rt::thread_cleanup`] to reset the thread
323/// handle.
324pub(crate) fn drop_current() {
325let current = CURRENT.get();
326if current > DESTROYED {
327unsafe {
328CURRENT.set(DESTROYED);
329drop(Thread::from_raw(current));
330 }
331 }
332}