std/thread/current.rs
1use super::id::ThreadId;
2use super::main_thread;
3use super::thread::Thread;
4use crate::mem::ManuallyDrop;
5use crate::ptr;
6use crate::sys::thread as imp;
7use crate::sys::thread_local::local_pointer;
8
9const NONE: *mut () = ptr::null_mut();
10const BUSY: *mut () = ptr::without_provenance_mut(1);
11const DESTROYED: *mut () = ptr::without_provenance_mut(2);
12
13local_pointer! {
14 static CURRENT;
15}
16
17/// 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 {
22 use super::*;
23
24 cfg_select! {
25 target_thread_local => {
26 use crate::cell::Cell;
27
28 #[thread_local]
29 static ID: Cell<Option<ThreadId>> = Cell::new(None);
30
31 pub(super) const CHEAP: bool = true;
32
33 pub(crate) fn get() -> Option<ThreadId> {
34 ID.get()
35 }
36
37 pub(super) fn set(id: ThreadId) {
38 ID.set(Some(id))
39 }
40 }
41 target_pointer_width = "16" => {
42 local_pointer! {
43 static ID0;
44 static ID16;
45 static ID32;
46 static ID48;
47 }
48
49 pub(super) const CHEAP: bool = false;
50
51 pub(crate) fn get() -> Option<ThreadId> {
52 let id0 = ID0.get().addr() as u64;
53 let id16 = ID16.get().addr() as u64;
54 let id32 = ID32.get().addr() as u64;
55 let id48 = ID48.get().addr() as u64;
56 ThreadId::from_u64((id48 << 48) + (id32 << 32) + (id16 << 16) + id0)
57 }
58
59 pub(super) fn set(id: ThreadId) {
60 let 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" => {
68 local_pointer! {
69 static ID0;
70 static ID32;
71 }
72
73 pub(super) const CHEAP: bool = false;
74
75 pub(crate) fn get() -> Option<ThreadId> {
76 let id0 = ID0.get().addr() as u64;
77 let id32 = ID32.get().addr() as u64;
78 ThreadId::from_u64((id32 << 32) + id0)
79 }
80
81 pub(super) fn set(id: ThreadId) {
82 let 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 _ => {
88 local_pointer! {
89 static ID;
90 }
91
92 pub(super) const CHEAP: bool = true;
93
94 pub(crate) fn get() -> Option<ThreadId> {
95 let id = ID.get().addr() as u64;
96 ThreadId::from_u64(id)
97 }
98
99 pub(super) fn set(id: ThreadId) {
100 let val = id.as_u64().get();
101 ID.set(ptr::without_provenance_mut(val as usize));
102 }
103 }
104 }
105
106 #[inline]
107 pub(super) fn get_or_init() -> ThreadId {
108 get().unwrap_or_else(
109 #[cold]
110 || {
111 let id = ThreadId::new();
112 id::set(id);
113 id
114 },
115 )
116 }
117}
118
119/// 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> {
122 if CURRENT.get() != NONE {
123 return Err(thread);
124 }
125
126 match id::get() {
127 Some(id) if id == thread.id() => {}
128 None => id::set(thread.id()),
129 _ => return Err(thread),
130 }
131
132 // Make sure that `crate::rt::thread_cleanup` will be run, which will
133 // call `drop_current`.
134 crate::sys::thread_local::guard::enable();
135 CURRENT.set(thread.into_raw().cast_mut());
136 Ok(())
137}
138
139/// 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.
168 if !id::CHEAP {
169 if let Some(id) = try_with_current(|t| t.map(|t| t.id())) {
170 return id;
171 }
172 }
173
174 id::get_or_init()
175}
176
177/// 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}
187
188/// 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
192 F: FnOnce(Option<&Thread>) -> R,
193{
194 let current = CURRENT.get();
195 if 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.
199 unsafe {
200 let current = ManuallyDrop::new(Thread::from_raw(current));
201 f(Some(¤t))
202 }
203 } else {
204 f(None)
205 }
206}
207
208/// 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
214 F: FnOnce(Option<&str>) -> R,
215{
216 try_with_current(|thread| {
217 let name = if let Some(thread) = thread {
218 // If there is a current thread handle, try to use the name stored
219 // there.
220 thread.name()
221 } else if let Some(main) = main_thread::get()
222 && let Some(id) = id::get()
223 && id == main
224 {
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.
229 Some("main")
230 } else {
231 None
232 };
233
234 f(name)
235 })
236}
237
238/// 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 {
242 let current = CURRENT.get();
243 if current > DESTROYED {
244 unsafe {
245 let current = ManuallyDrop::new(Thread::from_raw(current));
246 (*current).clone()
247 }
248 } else if current == DESTROYED {
249 Thread::new(id::get_or_init(), None)
250 } else {
251 init_current(current)
252 }
253}
254
255/// 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 {
277 let current = CURRENT.get();
278 if current > DESTROYED {
279 unsafe {
280 let current = ManuallyDrop::new(Thread::from_raw(current));
281 (*current).clone()
282 }
283 } else {
284 init_current(current)
285 }
286}
287
288#[cold]
289fn init_current(current: *mut ()) -> Thread {
290 if current == NONE {
291 CURRENT.set(BUSY);
292 // If the thread ID was initialized already, use it.
293 let id = id::get_or_init();
294 let thread = Thread::new(id, None);
295
296 // Make sure that `crate::rt::thread_cleanup` will be run, which will
297 // call `drop_current`.
298 crate::sys::thread_local::guard::enable();
299 CURRENT.set(thread.clone().into_raw().cast_mut());
300 thread
301 } 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 rtabort!(
311 "init_current() was re-entrant, which indicates a bug in the Rust threading implementation"
312 )
313 } else {
314 debug_assert_eq!(current, DESTROYED);
315 panic!(
316 "use of std::thread::current() is not possible after the thread's \
317 local data has been destroyed"
318 )
319 }
320}
321
322/// This should be run in [`crate::rt::thread_cleanup`] to reset the thread
323/// handle.
324pub(crate) fn drop_current() {
325 let current = CURRENT.get();
326 if current > DESTROYED {
327 unsafe {
328 CURRENT.set(DESTROYED);
329 drop(Thread::from_raw(current));
330 }
331 }
332}