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(&current))
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}