Skip to main content

std/thread/
thread.rs

1use super::id::ThreadId;
2use super::main_thread;
3use crate::alloc::System;
4use crate::ffi::CStr;
5use crate::fmt;
6use crate::pin::Pin;
7use crate::sync::{Arc, OnceLock};
8use crate::sys::sync::Parker;
9use crate::sys::thread as imp;
10use crate::time::Duration;
11
12// This module ensures private fields are kept private, which is necessary to enforce the safety requirements.
13mod thread_name_string {
14    use crate::ffi::{CStr, CString};
15    use crate::str;
16
17    /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated.
18    pub(crate) struct ThreadNameString {
19        inner: CString,
20    }
21
22    impl From<String> for ThreadNameString {
23        fn from(s: String) -> Self {
24            Self {
25                inner: CString::new(s).expect("thread name may not contain interior null bytes"),
26            }
27        }
28    }
29
30    impl ThreadNameString {
31        pub(crate) fn as_cstr(&self) -> &CStr {
32            &self.inner
33        }
34
35        pub(crate) fn as_str(&self) -> &str {
36            // SAFETY: `ThreadNameString` is guaranteed to be UTF-8.
37            unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) }
38        }
39    }
40}
41
42use thread_name_string::ThreadNameString;
43
44/// The internal representation of a `Thread` handle
45///
46/// We explicitly set the alignment for our guarantee in Thread::into_raw. This
47/// allows applications to stuff extra metadata bits into the alignment, which
48/// can be rather useful when working with atomics.
49#[repr(align(8))]
50struct Inner {
51    name: Option<ThreadNameString>,
52    id: ThreadId,
53    os_id: OnceLock<u64>,
54    parker: Parker,
55}
56
57impl Inner {
58    fn parker(self: Pin<&Self>) -> Pin<&Parker> {
59        unsafe { Pin::map_unchecked(self, |inner| &inner.parker) }
60    }
61}
62
63#[derive(Clone)]
64#[stable(feature = "rust1", since = "1.0.0")]
65/// A handle to a thread.
66///
67/// Threads are represented via the `Thread` type, which you can get in one of
68/// two ways:
69///
70/// * By spawning a new thread, e.g., using the [`thread::spawn`]
71///   function, and calling [`thread`] on the [`JoinHandle`].
72/// * By requesting the current thread, using the [`thread::current`] function.
73///
74/// The [`thread::current`] function is available even for threads not spawned
75/// by the APIs of this module.
76///
77/// There is usually no need to create a `Thread` struct yourself, one
78/// should instead use a function like `spawn` to create new threads, see the
79/// docs of [`Builder`] and [`spawn`] for more details.
80///
81/// [`thread::spawn`]: super::spawn
82/// [`thread`]: super::JoinHandle::thread
83/// [`JoinHandle`]: super::JoinHandle
84/// [`thread::current`]: super::current::current
85/// [`Builder`]: super::Builder
86/// [`spawn`]: super::spawn
87pub struct Thread {
88    // We use the System allocator such that creating or dropping this handle
89    // does not interfere with a potential Global allocator using thread-local
90    // storage.
91    inner: Pin<Arc<Inner, System>>,
92}
93
94impl Thread {
95    pub(crate) fn new(id: ThreadId, name: Option<String>) -> Thread {
96        let name = name.map(ThreadNameString::from);
97
98        // We have to use `unsafe` here to construct the `Parker` in-place,
99        // which is required for the UNIX implementation.
100        //
101        // SAFETY: We pin the Arc immediately after creation, so its address never
102        // changes.
103        let inner = unsafe {
104            let mut arc = Arc::<Inner, _>::new_uninit_in(System);
105            let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr();
106            (&raw mut (*ptr).name).write(name);
107            (&raw mut (*ptr).id).write(id);
108            (&raw mut (*ptr).os_id).write(OnceLock::new());
109            Parker::new_in_place(&raw mut (*ptr).parker);
110            Pin::new_unchecked(arc.assume_init())
111        };
112
113        Thread { inner }
114    }
115
116    /// Creates a handle for the calling thread, recording its OS id.
117    ///
118    /// `id` must be the `ThreadId` of the calling thread.
119    ///
120    /// Takes no name because passing one into `Thread::new` allocates with the
121    /// global allocator, which `thread::current` is documented never to use.
122    pub(crate) fn new_current(id: ThreadId) -> Thread {
123        let thread = Thread::new(id, None);
124        thread.set_os_id_to_current();
125        thread
126    }
127
128    /// Records the calling thread's OS id, as reported by
129    /// `imp::current_os_id`, in this handle.
130    ///
131    /// May only be called from the thread to which this handle belongs. A
132    /// spawned thread does this itself once it starts running, since its handle
133    /// already exists by then.
134    ///
135    /// `imp::current_os_id` must not allocate with the global allocator or call
136    /// `thread::current`.
137    pub(crate) fn set_os_id_to_current(&self) {
138        if let Some(os_id) = imp::current_os_id() {
139            if self.inner.os_id.set(os_id).is_err() {
140                rtabort!("thread OS id already set");
141            }
142        }
143    }
144
145    /// Like the public [`park`], but callable on any handle. This is used to
146    /// allow parking in TLS destructors.
147    ///
148    /// # Safety
149    /// May only be called from the thread to which this handle belongs.
150    ///
151    /// [`park`]: super::park
152    pub(crate) unsafe fn park(&self) {
153        unsafe { self.inner.as_ref().parker().park() }
154    }
155
156    /// Like the public [`park_timeout`], but callable on any handle. This is
157    /// used to allow parking in TLS destructors.
158    ///
159    /// # Safety
160    /// May only be called from the thread to which this handle belongs.
161    ///
162    /// [`park_timeout`]: super::park_timeout
163    pub(crate) unsafe fn park_timeout(&self, dur: Duration) {
164        unsafe { self.inner.as_ref().parker().park_timeout(dur) }
165    }
166
167    /// Atomically makes the handle's token available if it is not already.
168    ///
169    /// Every thread is equipped with some basic low-level blocking support, via
170    /// the [`park`] function and the `unpark()` method. These can be used as a
171    /// more CPU-efficient implementation of a spinlock.
172    ///
173    /// See the [park documentation] for more details.
174    ///
175    /// # Examples
176    ///
177    /// ```
178    /// use std::thread;
179    /// use std::time::Duration;
180    /// use std::sync::atomic::{AtomicBool, Ordering};
181    ///
182    /// static QUEUED: AtomicBool = AtomicBool::new(false);
183    ///
184    /// let parked_thread = thread::Builder::new()
185    ///     .spawn(|| {
186    ///         println!("Parking thread");
187    ///         QUEUED.store(true, Ordering::Release);
188    ///         thread::park();
189    ///         println!("Thread unparked");
190    ///     })
191    ///     .unwrap();
192    ///
193    /// // Let some time pass for the thread to be spawned.
194    /// thread::sleep(Duration::from_millis(10));
195    ///
196    /// // Wait until the other thread is queued.
197    /// // This is crucial! It guarantees that the `unpark` below is not consumed
198    /// // by some other code in the parked thread (e.g. inside `println!`).
199    /// while !QUEUED.load(Ordering::Acquire) {
200    ///     // Spinning is of course inefficient; in practice, this would more likely be
201    ///     // a dequeue where we have no work to do if there's nobody queued.
202    ///     std::hint::spin_loop();
203    /// }
204    ///
205    /// println!("Unpark the thread");
206    /// parked_thread.thread().unpark();
207    ///
208    /// parked_thread.join().unwrap();
209    /// ```
210    ///
211    /// [`park`]: super::park
212    /// [park documentation]: super::park
213    #[stable(feature = "rust1", since = "1.0.0")]
214    #[inline]
215    pub fn unpark(&self) {
216        self.inner.as_ref().parker().unpark();
217    }
218
219    /// Gets the thread's unique identifier.
220    ///
221    /// # Examples
222    ///
223    /// ```
224    /// use std::thread;
225    ///
226    /// let other_thread = thread::spawn(|| {
227    ///     thread::current().id()
228    /// });
229    ///
230    /// let other_thread_id = other_thread.join().unwrap();
231    /// assert!(thread::current().id() != other_thread_id);
232    /// ```
233    #[stable(feature = "thread_id", since = "1.19.0")]
234    #[must_use]
235    pub fn id(&self) -> ThreadId {
236        self.inner.id
237    }
238
239    /// Gets the id the operating system gave this thread, if it has one that can
240    /// be read.
241    ///
242    /// This is the id that shows up in tools like `ps` and `top`, debuggers and
243    /// crash logs, unlike [`ThreadId`], which has no guaranteed relationship to
244    /// it. On a platform with no OS-visible thread id, such as SGX, the value
245    /// may be some other per-thread value (there, the thread's address), which
246    /// such tools will not recognize. `None` means no id could be recorded: the
247    /// thread has not started running yet, or the platform has no way to read
248    /// one.
249    ///
250    /// The operating system may reuse the id of a thread that has exited, and a
251    /// `Thread` handle can outlive the thread it refers to. After a `fork`, the
252    /// id recorded in the child process still refers to the parent's thread; it
253    /// is not re-read. Use the id only where a reused or stale id is harmless,
254    /// such as logging.
255    ///
256    /// # Examples
257    ///
258    /// ```
259    /// #![feature(thread_os_id)]
260    /// use std::thread;
261    ///
262    /// let spawned = thread::spawn(|| thread::current().os_id()).join().unwrap();
263    /// if spawned.is_some() {
264    ///     assert_ne!(spawned, thread::current().os_id());
265    /// }
266    /// ```
267    #[unstable(feature = "thread_os_id", issue = "160215")]
268    #[must_use]
269    pub fn os_id(&self) -> Option<u64> {
270        self.inner.os_id.get().copied()
271    }
272
273    /// Gets the thread's name.
274    ///
275    /// For more information about named threads, see
276    /// [this module-level documentation][naming-threads].
277    ///
278    /// # Examples
279    ///
280    /// Threads by default have no name specified:
281    ///
282    /// ```
283    /// use std::thread;
284    ///
285    /// let builder = thread::Builder::new();
286    ///
287    /// let handler = builder.spawn(|| {
288    ///     assert!(thread::current().name().is_none());
289    /// }).unwrap();
290    ///
291    /// handler.join().unwrap();
292    /// ```
293    ///
294    /// Thread with a specified name:
295    ///
296    /// ```
297    /// use std::thread;
298    ///
299    /// let builder = thread::Builder::new()
300    ///     .name("foo".into());
301    ///
302    /// let handler = builder.spawn(|| {
303    ///     assert_eq!(thread::current().name(), Some("foo"))
304    /// }).unwrap();
305    ///
306    /// handler.join().unwrap();
307    /// ```
308    ///
309    /// [naming-threads]: ./index.html#naming-threads
310    #[stable(feature = "rust1", since = "1.0.0")]
311    #[must_use]
312    pub fn name(&self) -> Option<&str> {
313        if let Some(name) = &self.inner.name {
314            Some(name.as_str())
315        } else if main_thread::get() == Some(self.inner.id) {
316            Some("main")
317        } else {
318            None
319        }
320    }
321
322    /// Consumes the `Thread`, returning a raw pointer.
323    ///
324    /// To avoid a memory leak the pointer must be converted
325    /// back into a `Thread` using [`Thread::from_raw`]. The pointer is
326    /// guaranteed to be aligned to at least 8 bytes.
327    ///
328    /// # Examples
329    ///
330    /// ```
331    /// #![feature(thread_raw)]
332    ///
333    /// use std::thread::{self, Thread};
334    ///
335    /// let thread = thread::current();
336    /// let id = thread.id();
337    /// let ptr = Thread::into_raw(thread);
338    /// unsafe {
339    ///     assert_eq!(Thread::from_raw(ptr).id(), id);
340    /// }
341    /// ```
342    #[unstable(feature = "thread_raw", issue = "97523")]
343    pub fn into_raw(self) -> *const () {
344        // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant.
345        let inner = unsafe { Pin::into_inner_unchecked(self.inner) };
346        Arc::into_raw_with_allocator(inner).0 as *const ()
347    }
348
349    /// Constructs a `Thread` from a raw pointer.
350    ///
351    /// The raw pointer must have been previously returned
352    /// by a call to [`Thread::into_raw`].
353    ///
354    /// # Safety
355    ///
356    /// This function is unsafe because improper use may lead
357    /// to memory unsafety, even if the returned `Thread` is never
358    /// accessed.
359    ///
360    /// Creating a `Thread` from a pointer other than one returned
361    /// from [`Thread::into_raw`] is **undefined behavior**.
362    ///
363    /// Calling this function twice on the same raw pointer can lead
364    /// to a double-free if both `Thread` instances are dropped.
365    #[unstable(feature = "thread_raw", issue = "97523")]
366    pub unsafe fn from_raw(ptr: *const ()) -> Thread {
367        // Safety: Upheld by caller.
368        unsafe {
369            Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) }
370        }
371    }
372
373    pub(crate) fn cname(&self) -> Option<&CStr> {
374        if let Some(name) = &self.inner.name {
375            Some(name.as_cstr())
376        } else if main_thread::get() == Some(self.inner.id) {
377            Some(c"main")
378        } else {
379            None
380        }
381    }
382}
383
384#[stable(feature = "rust1", since = "1.0.0")]
385impl fmt::Debug for Thread {
386    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387        f.debug_struct("Thread")
388            .field("id", &self.id())
389            .field("name", &self.name())
390            .finish_non_exhaustive()
391    }
392}