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}