From e57df9220a7c1aadc3ae8f0258baa4047f46bcfc Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 29 Nov 2025 15:12:28 +0100 Subject: [PATCH 1/5] std: split up the `thread` module (preparation) --- library/std/src/thread/builder.rs | 2146 +++++++++++++++++++++++++ library/std/src/thread/functions.rs | 2146 +++++++++++++++++++++++++ library/std/src/thread/id.rs | 2146 +++++++++++++++++++++++++ library/std/src/thread/join_handle.rs | 2146 +++++++++++++++++++++++++ library/std/src/thread/lifecycle.rs | 2146 +++++++++++++++++++++++++ library/std/src/thread/main_thread.rs | 2146 +++++++++++++++++++++++++ library/std/src/thread/thread.rs | 2146 +++++++++++++++++++++++++ 7 files changed, 15022 insertions(+) create mode 100644 library/std/src/thread/builder.rs create mode 100644 library/std/src/thread/functions.rs create mode 100644 library/std/src/thread/id.rs create mode 100644 library/std/src/thread/join_handle.rs create mode 100644 library/std/src/thread/lifecycle.rs create mode 100644 library/std/src/thread/main_thread.rs create mode 100644 library/std/src/thread/thread.rs diff --git a/library/std/src/thread/builder.rs b/library/std/src/thread/builder.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/builder.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} diff --git a/library/std/src/thread/functions.rs b/library/std/src/thread/functions.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/functions.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} diff --git a/library/std/src/thread/id.rs b/library/std/src/thread/id.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/id.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} diff --git a/library/std/src/thread/join_handle.rs b/library/std/src/thread/join_handle.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/join_handle.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/lifecycle.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} diff --git a/library/std/src/thread/main_thread.rs b/library/std/src/thread/main_thread.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/main_thread.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} diff --git a/library/std/src/thread/thread.rs b/library/std/src/thread/thread.rs new file mode 100644 index 0000000000000..983d189b07024 --- /dev/null +++ b/library/std/src/thread/thread.rs @@ -0,0 +1,2146 @@ +//! Native threads. +//! +//! ## The threading model +//! +//! An executing Rust program consists of a collection of native OS threads, +//! each with their own stack and local state. Threads can be named, and +//! provide some built-in support for low-level synchronization. +//! +//! Communication between threads can be done through +//! [channels], Rust's message-passing types, along with [other forms of thread +//! synchronization](../../std/sync/index.html) and shared-memory data +//! structures. In particular, types that are guaranteed to be +//! threadsafe are easily shared between threads using the +//! atomically-reference-counted container, [`Arc`]. +//! +//! Fatal logic errors in Rust cause *thread panic*, during which +//! a thread will unwind the stack, running destructors and freeing +//! owned resources. While not meant as a 'try/catch' mechanism, panics +//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with +//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered +//! from, or alternatively be resumed with +//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic +//! is not caught the thread will exit, but the panic may optionally be +//! detected from a different thread with [`join`]. If the main thread panics +//! without the panic being caught, the application will exit with a +//! non-zero exit code. +//! +//! When the main thread of a Rust program terminates, the entire program shuts +//! down, even if other threads are still running. However, this module provides +//! convenient facilities for automatically waiting for the termination of a +//! thread (i.e., join). +//! +//! ## Spawning a thread +//! +//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: +//! +//! ```rust +//! use std::thread; +//! +//! thread::spawn(move || { +//! // some work here +//! }); +//! ``` +//! +//! In this example, the spawned thread is "detached," which means that there is +//! no way for the program to learn when the spawned thread completes or otherwise +//! terminates. +//! +//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] +//! object that is returned by the call to [`spawn`], which provides +//! a `join` method that allows the caller to wait for the completion of the +//! spawned thread: +//! +//! ```rust +//! use std::thread; +//! +//! let thread_join_handle = thread::spawn(move || { +//! // some work here +//! }); +//! // some work here +//! let res = thread_join_handle.join(); +//! ``` +//! +//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final +//! value produced by the spawned thread, or [`Err`] of the value given to +//! a call to [`panic!`] if the thread panicked. +//! +//! Note that there is no parent/child relationship between a thread that spawns a +//! new thread and the thread being spawned. In particular, the spawned thread may or +//! may not outlive the spawning thread, unless the spawning thread is the main thread. +//! +//! ## Configuring threads +//! +//! A new thread can be configured before it is spawned via the [`Builder`] type, +//! which currently allows you to set the name and stack size for the thread: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::thread; +//! +//! thread::Builder::new().name("thread1".to_string()).spawn(move || { +//! println!("Hello, world!"); +//! }); +//! ``` +//! +//! ## The `Thread` type +//! +//! Threads are represented via the [`Thread`] type, which you can get in one of +//! two ways: +//! +//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. +//! +//! The [`thread::current`] function is available even for threads not spawned +//! by the APIs of this module. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread-local storage for Rust +//! programs. Thread-local storage is a method of storing data into a global +//! variable that each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! A thread-local key owns the value it contains and will destroy the value when the +//! thread exits. It is created with the [`thread_local!`] macro and can contain any +//! value that is `'static` (no borrowed pointers). It provides an accessor function, +//! [`with`], that yields a shared reference to the value to the specified +//! closure. Thread-local keys allow only shared access to values, as there would be no +//! way to guarantee uniqueness if mutable borrows were allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! [`Cell`] or [`RefCell`] types. +//! +//! ## Naming threads +//! +//! Threads are able to have associated names for identification purposes. By default, spawned +//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass +//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the +//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: +//! +//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. +//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in +//! unix-like platforms). +//! +//! ## Stack size +//! +//! The default stack size is platform-dependent and subject to change. +//! Currently, it is 2 MiB on all Tier-1 platforms. +//! +//! There are two ways to manually specify the stack size for spawned threads: +//! +//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. +//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. +//! +//! Note that the stack size of the main thread is *not* determined by Rust. +//! +//! [channels]: crate::sync::mpsc +//! [`join`]: JoinHandle::join +//! [`Result`]: crate::result::Result +//! [`Ok`]: crate::result::Result::Ok +//! [`Err`]: crate::result::Result::Err +//! [`thread::current`]: current::current +//! [`thread::Result`]: Result +//! [`unpark`]: Thread::unpark +//! [`thread::park_timeout`]: park_timeout +//! [`Cell`]: crate::cell::Cell +//! [`RefCell`]: crate::cell::RefCell +//! [`with`]: LocalKey::with +//! [`thread_local!`]: crate::thread_local + +#![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] + +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; + +use crate::alloc::System; +use crate::any::Any; +use crate::cell::UnsafeCell; +use crate::ffi::CStr; +use crate::marker::PhantomData; +use crate::mem::{self, ManuallyDrop, forget}; +use crate::num::NonZero; +use crate::pin::Pin; +use crate::sync::Arc; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sys::sync::Parker; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; +use crate::time::{Duration, Instant}; +use crate::{env, fmt, io, panic, panicking, str}; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +mod scoped; + +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; + +mod current; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use current::current; +#[unstable(feature = "current_thread_id", issue = "147194")] +pub use current::current_id; +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; +use current::{set_current, try_with_current}; + +mod spawnhook; + +#[unstable(feature = "thread_spawn_hook", issue = "132951")] +pub use spawnhook::add_spawn_hook; + +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod local; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::local::{AccessError, LocalKey}; + +// Implementation details used by the thread_local!{} macro. +#[doc(hidden)] +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use super::local::thread_local_process_attrs; + pub use crate::sys::thread_local::*; +} + +/// The data passed to the spawned thread for thread initialization. Any thread +/// implementation should start a new thread by calling .init() on this before +/// doing anything else to ensure the current thread is properly initialized and +/// the global allocator works. +pub(crate) struct ThreadInit { + pub handle: Thread, + pub rust_start: Box, +} + +impl ThreadInit { + /// Initialize the 'current thread' mechanism on this thread, returning the + /// Rust entry point. + pub fn init(self: Box) -> Box { + // Set the current thread before any (de)allocations on the global allocator occur, + // so that it may call std::thread::current() in its implementation. This is also + // why we take Box, to ensure the Box is not destroyed until after this point. + // Cloning the handle does not invoke the global allocator, it is an Arc. + if let Err(_thread) = set_current(self.handle.clone()) { + // The current thread should not have set yet. Use an abort to save binary size (see #123356). + rtabort!("current thread handle already set during thread spawn"); + } + + if let Some(name) = self.handle.cname() { + imp::set_name(name); + } + + self.rust_start + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// + +/// Thread factory, which can be used in order to configure the properties of +/// a new thread. +/// +/// Methods can be chained on it in order to configure it. +/// +/// The two configurations available are: +/// +/// - [`name`]: specifies an [associated name for the thread][naming-threads] +/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] +/// +/// The [`spawn`] method will take ownership of the builder and create an +/// [`io::Result`] to the thread handle with the given configuration. +/// +/// The [`thread::spawn`] free function uses a `Builder` with default +/// configuration and [`unwrap`]s its return value. +/// +/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want +/// to recover from a failure to launch a thread, indeed the free function will +/// panic where the `Builder` method will return a [`io::Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// [`stack_size`]: Builder::stack_size +/// [`name`]: Builder::name +/// [`spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +/// [`io::Result`]: crate::io::Result +/// [`unwrap`]: crate::result::Result::unwrap +/// [naming-threads]: ./index.html#naming-threads +/// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Builder { + // A name for the thread-to-be, for identification in panic messages + name: Option, + // The size of the stack for the spawned thread in bytes + stack_size: Option, + // Skip running and inheriting the thread spawn hooks + no_hooks: bool, +} + +impl Builder { + /// Generates the base configuration for spawning a thread, from which + /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(32 * 1024); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> Builder { + Builder { name: None, stack_size: None, no_hooks: false } + } + + /// Names the thread-to-be. Currently the name is used for identification + /// only in panic messages. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + pub fn name(mut self, name: String) -> Builder { + self.name = Some(name); + self + } + + /// Sets the size of the stack (in bytes) for the new thread. + /// + /// The actual stack size may be greater than this value if + /// the platform specifies a minimal stack size. + /// + /// For more information about the stack size for threads, see + /// [this module-level documentation][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(32 * 1024); + /// ``` + /// + /// [stack-size]: ./index.html#stack-size + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stack_size(mut self, size: usize) -> Builder { + self.stack_size = Some(size); + self + } + + /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// + /// Use this if the parent thread is in no way relevant for the child thread. + /// For example, when lazily spawning threads for a thread pool. + #[unstable(feature = "thread_spawn_hook", issue = "132951")] + pub fn no_hooks(mut self) -> Builder { + self.no_hooks = true; + self + } + + /// Spawns a new thread by taking ownership of the `Builder`, and returns an + /// [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + + /// Spawns a new thread without any lifetime restrictions by taking ownership + /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. + /// + /// The spawned thread may outlive the caller (unless the caller thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes). The join handle can be used to block on + /// termination of the spawned thread, including recovering its panics. + /// + /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], + /// except for the relaxed lifetime bounds, which render it unsafe. + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// + /// # Errors + /// + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Safety + /// + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: + /// + /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced + /// data is dropped + /// - use only types with `'static` lifetime bounds, i.e., those with no or only + /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] + /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let x = 1; + /// let thread_x = &x; + /// + /// let handler = unsafe { + /// builder.spawn_unchecked(move || { + /// println!("x = {}", *thread_x); + /// }).unwrap() + /// }; + /// + /// // caller has to ensure `join()` is called, otherwise + /// // it is possible to access freed memory if `x` gets + /// // dropped before the thread closure is executed! + /// handler.join().unwrap(); + /// ``` + /// + /// [`io::Result`]: crate::io::Result + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) + } + + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn spawn_unchecked_<'scope, F, T>( + self, + f: F, + scope_data: Option>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send, + T: Send, + { + let Builder { name, stack_size, no_hooks } = self; + + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); + + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } + + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(mem::MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(mem::MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } + + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw( + Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) + ) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawns a new thread, returning a [`JoinHandle`] for it. +/// +/// The join handle provides a [`join`] method that can be used to join the spawned +/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing +/// the argument given to [`panic!`]. +/// +/// If the join handle is dropped, the spawned thread will implicitly be *detached*. +/// In this case, the spawned thread may no longer be joined. +/// (It is the responsibility of the program to either eventually join threads it +/// creates or detach them; otherwise, a resource leak will result.) +/// +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. +/// +/// As you can see in the signature of `spawn` there are two constraints on +/// both the closure given to `spawn` and its return value, let's explain them: +/// +/// - The `'static` constraint means that the closure and its return value +/// must have a lifetime of the whole program execution. The reason for this +/// is that threads can outlive the lifetime they have been created in. +/// +/// Indeed if the thread, and by extension its return value, can outlive their +/// caller, we need to make sure that they will be valid afterwards, and since +/// we *can't* know when it will return we need to have them valid as long as +/// possible, that is until the end of the program, hence the `'static` +/// lifetime. +/// - The [`Send`] constraint is because the closure will need to be passed +/// *by value* from the thread where it is spawned to the new thread. Its +/// return value will need to be passed from the new thread to the thread +/// where it is `join`ed. +/// As a reminder, the [`Send`] marker trait expresses that it is safe to be +/// passed from thread to thread. [`Sync`] expresses that it is safe to have a +/// reference be passed from thread to thread. +/// +/// # Panics +/// +/// Panics if the OS fails to create a thread; use [`Builder::spawn`] +/// to recover from such errors. +/// +/// # Examples +/// +/// Creating a thread. +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::spawn(|| { +/// // thread code +/// }); +/// +/// handler.join().unwrap(); +/// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{value}"); +/// }); +/// +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{result}"); +/// ``` +/// +/// # Notes +/// +/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. +/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a +/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` +/// unwinds all the way to the root with such an exception, one of two behaviors are possible, +/// and it is unspecified which will occur: +/// +/// * The process aborts. +/// * The process does not abort, and [`join`] will return a `Result::Err` +/// containing an opaque type. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [`channels`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Err`]: crate::result::Result::Err +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn spawn(f: F) -> JoinHandle +where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +{ + Builder::new().spawn(f).expect("failed to spawn thread") +} + +/// Cooperatively gives up a timeslice to the OS scheduler. +/// +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. +/// +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. +/// +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. +/// +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// thread::yield_now(); +/// ``` +/// +/// [`channel`]: crate::sync::mpsc +/// [`join`]: JoinHandle::join +/// [`Condvar`]: crate::sync::Condvar +/// [`Mutex`]: crate::sync::Mutex +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + imp::yield_now() +} + +/// Determines whether the current thread is unwinding because of panic. +/// +/// A common use of this feature is to poison shared resources when writing +/// unsafe code, by checking `panicking` when the `drop` is called. +/// +/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] +/// already poison themselves when a thread panics while holding the lock. +/// +/// This can also be used in multithreaded applications, in order to send a +/// message to other threads warning that a thread has panicked (e.g., for +/// monitoring purposes). +/// +/// # Examples +/// +/// ```should_panic +/// use std::thread; +/// +/// struct SomeStruct; +/// +/// impl Drop for SomeStruct { +/// fn drop(&mut self) { +/// if thread::panicking() { +/// println!("dropped while unwinding"); +/// } else { +/// println!("dropped while not unwinding"); +/// } +/// } +/// } +/// +/// { +/// print!("a: "); +/// let a = SomeStruct; +/// } +/// +/// { +/// print!("b: "); +/// let b = SomeStruct; +/// panic!() +/// } +/// ``` +/// +/// [Mutex]: crate::sync::Mutex +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + panicking::panicking() +} + +/// Uses [`sleep`]. +/// +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// +/// // Let's sleep for 2 seconds: +/// thread::sleep_ms(2000); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] +pub fn sleep_ms(ms: u32) { + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for at least the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. It will never sleep less. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// On Unix platforms, the underlying syscall may be interrupted by a +/// spurious wakeup or signal handler. To ensure the sleep occurs for at least +/// the specified duration, this function may invoke that system call multiple +/// times. +/// Platforms which do not support nanosecond precision for sleeping will +/// have `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// Currently, specifying a zero duration on Unix platforms returns immediately +/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows +/// platforms the underlying [`Sleep`] syscall is always invoked. +/// If the intention is to yield the current time-slice you may want to use +/// [`yield_now`] instead. +/// +/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep +/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep +/// +/// # Examples +/// +/// ```no_run +/// use std::{thread, time}; +/// +/// let ten_millis = time::Duration::from_millis(10); +/// let now = time::Instant::now(); +/// +/// thread::sleep(ten_millis); +/// +/// assert!(now.elapsed() >= ten_millis); +/// ``` +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + +/// Puts the current thread to sleep until the specified deadline has passed. +/// +/// The thread may still be asleep after the deadline specified due to +/// scheduling specifics or platform-dependent functionality. It will never +/// wake before. +/// +/// This function is blocking, and should not be used in `async` functions. +/// +/// # Platform-specific behavior +/// +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. +/// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. +/// +/// # Examples +/// +/// A simple game loop that limits the game to 60 frames per second. +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # fn update() {} +/// # fn render() {} +/// # +/// let max_fps = 60.0; +/// let frame_time = Duration::from_secs_f32(1.0/max_fps); +/// let mut next_frame = Instant::now(); +/// loop { +/// thread::sleep_until(next_frame); +/// next_frame += frame_time; +/// update(); +/// render(); +/// } +/// ``` +/// +/// A slow API we must not call too fast and which takes a few +/// tries before succeeding. By using `sleep_until` the time the +/// API call takes does not influence when we retry or when we give up +/// +/// ```no_run +/// #![feature(thread_sleep_until)] +/// # use std::time::{Duration, Instant}; +/// # use std::thread; +/// # +/// # enum Status { +/// # Ready(usize), +/// # Waiting, +/// # } +/// # fn slow_web_api_call() -> Status { Status::Ready(42) } +/// # +/// # const MAX_DURATION: Duration = Duration::from_secs(10); +/// # +/// # fn try_api_call() -> Result { +/// let deadline = Instant::now() + MAX_DURATION; +/// let delay = Duration::from_millis(250); +/// let mut next_attempt = Instant::now(); +/// loop { +/// if Instant::now() > deadline { +/// break Err(()); +/// } +/// if let Status::Ready(data) = slow_web_api_call() { +/// break Ok(data); +/// } +/// +/// next_attempt = deadline.min(next_attempt + delay); +/// thread::sleep_until(next_attempt); +/// } +/// # } +/// # let _data = try_api_call(); +/// ``` +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub fn sleep_until(deadline: Instant) { + imp::sleep_until(deadline) +} + +/// Used to ensure that `park` and `park_timeout` do not unwind, as that can +/// cause undefined behavior if not handled correctly (see #102398 for context). +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("an irrecoverable error occurred while synchronizing threads") + } +} + +/// Blocks unless or until the current thread's token is made available. +/// +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. However, +/// it is guaranteed that this function will not panic (it may abort the +/// process if the implementation encounters some rare errors). +/// +/// # `park` and `unpark` +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. Because the token can be held by a thread even if it is currently not +/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. +/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens +/// after all `park` that may be done by other data structures! +/// +/// The API is typically used by acquiring a handle to the current thread, placing that handle in a +/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some +/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point +/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it +/// will be woken up properly. +/// +/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread +/// without first establishing that it is about to be `park`ing within your code, that `unpark` may +/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means +/// you must not call unknown code between setting up for parking and calling `park`; for instance, +/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a +/// deadlock. +/// +/// The motivation for this design is twofold: +/// +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. +/// +/// * It can be implemented very efficiently on many platforms. +/// +/// # Memory Ordering +/// +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory +/// operations performed before a call to `unpark` are made visible to the thread that +/// consumes the token and returns from `park`. Note that all `park` and `unpark` +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. +/// +/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` +/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same +/// thread form a [release sequence]. +/// +/// Note that being unblocked does not imply a call was made to `unpark`, because +/// wakeups can also be spurious. For example, a valid, but inefficient, +/// implementation could have `park` and `unpark` return immediately without doing anything, +/// making *all* wakeups spurious. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::sync::atomic::{Ordering, AtomicBool}; +/// use std::time::Duration; +/// +/// static QUEUED: AtomicBool = AtomicBool::new(false); +/// static FLAG: AtomicBool = AtomicBool::new(false); +/// +/// let parked_thread = thread::spawn(move || { +/// println!("Thread spawned"); +/// // Signal that we are going to `park`. Between this store and our `park`, there may +/// // be no other `park`, or else that `park` could consume our `unpark` token! +/// QUEUED.store(true, Ordering::Release); +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !FLAG.load(Ordering::Acquire) { +/// // We can *not* use `println!` here since that could use thread parking internally. +/// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. +/// } +/// println!("Flag received"); +/// }); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// // Ensure the thread is about to park. +/// // This is crucial! It guarantees that the `unpark` below is not consumed +/// // by some other code in the parked thread (e.g. inside `println!`). +/// while !QUEUED.load(Ordering::Acquire) { +/// // Spinning is of course inefficient; in practice, this would more likely be +/// // a dequeue where we have no work to do if there's nobody queued. +/// std::hint::spin_loop(); +/// } +/// +/// // Set the flag, and let the thread wake up. +/// // There is no race condition here: if `unpark` +/// // happens first, `park` will return immediately. +/// // There is also no other `park` that could consume this token, +/// // since we waited until the other thread got queued. +/// // Hence there is no risk of a deadlock. +/// FLAG.store(true, Ordering::Release); +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`unpark`]: Thread::unpark +/// [`thread::park_timeout`]: park_timeout +/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let guard = PanicGuard; + // SAFETY: park_timeout is called on the parker owned by this thread. + unsafe { + current().park(); + } + // No panic occurred, do not abort. + forget(guard); +} + +/// Uses [`park_timeout`]. +/// +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `ms` long. +/// +/// See the [park documentation][`park`] for more detail. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] +pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as +/// preemption or platform differences that might not cause the maximum +/// amount of time waited to be precisely `dur` long. +/// +/// See the [park documentation][park] for more details. +/// +/// # Platform-specific behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Examples +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {elapsed:?}"); +/// timeout_remaining = timeout - elapsed; +/// } +/// ``` +#[stable(feature = "park_timeout", since = "1.4.0")] +pub fn park_timeout(dur: Duration) { + let guard = PanicGuard; + // SAFETY: park_timeout is called on a handle owned by this thread. + unsafe { + current().park_timeout(dur); + } + // No panic occurred, do not abort. + forget(guard); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreadId +//////////////////////////////////////////////////////////////////////////////// + +/// A unique identifier for a running thread. +/// +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let other_thread = thread::spawn(|| { +/// thread::current().id() +/// }); +/// +/// let other_thread_id = other_thread.join().unwrap(); +/// assert!(thread::current().id() != other_thread_id); +/// ``` +/// +/// [`id`]: Thread::id +#[stable(feature = "thread_id", since = "1.19.0")] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct ThreadId(NonZero); + +impl ThreadId { + // Generate a new unique thread ID. + pub(crate) fn new() -> ThreadId { + #[cold] + fn exhausted() -> ! { + panic!("failed to generate unique thread ID: bitspace exhausted") + } + + cfg_select! { + target_has_atomic = "64" => { + use crate::sync::atomic::{Atomic, AtomicU64}; + + static COUNTER: Atomic = AtomicU64::new(0); + + let mut last = COUNTER.load(Ordering::Relaxed); + loop { + let Some(id) = last.checked_add(1) else { + exhausted(); + }; + + match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => return ThreadId(NonZero::new(id).unwrap()), + Err(id) => last = id, + } + } + } + _ => { + use crate::cell::SyncUnsafeCell; + use crate::hint::spin_loop; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::thread::yield_now; + + // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex + // here as we might be trying to get the current thread id in the global allocator, + // and on some platforms Mutex requires allocation. + static COUNTER_LOCKED: Atomic = AtomicBool::new(false); + static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); + + // Acquire lock. + let mut spin = 0; + while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if spin <= 3 { + for _ in 0..(1 << spin) { + spin_loop(); + } + } else { + yield_now(); + } + spin += 1; + } + + // SAFETY: we have an exclusive lock on the counter. + unsafe { + if let Some(id) = (*COUNTER.get()).checked_add(1) { + *COUNTER.get() = id; + COUNTER_LOCKED.store(false, Ordering::Release); + ThreadId(NonZero::new(id).unwrap()) + } else { + COUNTER_LOCKED.store(false, Ordering::Release); + exhausted() + } + } + } + } + } + + #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] + fn from_u64(v: u64) -> Option { + NonZero::new(v).map(ThreadId) + } + + /// This returns a numeric identifier for the thread identified by this + /// `ThreadId`. + /// + /// As noted in the documentation for the type itself, it is essentially an + /// opaque ID, but is guaranteed to be unique for each thread. The returned + /// value is entirely opaque -- only equality testing is stable. Note that + /// it is not guaranteed which values new threads will return, and this may + /// change across Rust versions. + #[must_use] + #[unstable(feature = "thread_id_value", issue = "67939")] + pub fn as_u64(&self) -> NonZero { + self.0 + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + use crate::str; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + + impl From for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } + + impl ThreadNameString { + pub fn as_cstr(&self) -> &CStr { + &self.inner + } + + pub fn as_str(&self) -> &str { + // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. + unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + } + } +} + +use thread_name_string::ThreadNameString; + +/// Store the ID of the main thread. +/// +/// The thread handle for the main thread is created lazily, and this might even +/// happen pre-main. Since not every platform has a way to identify the main +/// thread when that happens – macOS's `pthread_main_np` function being a notable +/// exception – we cannot assign it the right name right then. Instead, in our +/// runtime startup code, we remember the thread ID of the main thread (through +/// this modules `set` function) and use it to identify the main thread from then +/// on. This works reliably and has the additional advantage that we can report +/// the right thread name on main even after the thread handle has been destroyed. +/// Note however that this also means that the name reported in pre-main functions +/// will be incorrect, but that's just something we have to live with. +pub(crate) mod main_thread { + cfg_select! { + target_has_atomic = "64" => { + use super::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; + + static MAIN: Atomic = AtomicU64::new(0); + + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) + } + } + _ => { + use super::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; + + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); + + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None + } + } + + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); + } + } + } +} + +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + if let Some(name) = &thread.inner.name { + return f(Some(name.as_str())); + } else if Some(thread.inner.id) == main_thread::get() { + // The main thread doesn't store its name in the handle, we must + // identify it through its ID. Since we already have the `Thread`, + // we can retrieve the ID from it instead of going through another + // thread local. + return f(Some("main")); + } + } else if let Some(main) = main_thread::get() + && let Some(id) = current::id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + return f(Some("main")); + } + + f(None) + }) +} + +/// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] +struct Inner { + name: Option, + id: ThreadId, + parker: Parker, +} + +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +/// A handle to a thread. +/// +/// Threads are represented via the `Thread` type, which you can get in one of +/// two ways: +/// +/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] +/// function, and calling [`thread`][`JoinHandle::thread`] on the +/// [`JoinHandle`]. +/// * By requesting the current thread, using the [`thread::current`] function. +/// +/// The [`thread::current`] function is available even for threads not spawned +/// by the APIs of this module. +/// +/// There is usually no need to create a `Thread` struct yourself, one +/// should instead use a function like `spawn` to create new threads, see the +/// docs of [`Builder`] and [`spawn`] for more details. +/// +/// [`thread::current`]: current::current +pub struct Thread { + // We use the System allocator such that creating or dropping this handle + // does not interfere with a potential Global allocator using thread-local + // storage. + inner: Pin>, +} + +impl Thread { + pub(crate) fn new(id: ThreadId, name: Option) -> Thread { + let name = name.map(ThreadNameString::from); + + // We have to use `unsafe` here to construct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::::new_uninit_in(System); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + (&raw mut (*ptr).name).write(name); + (&raw mut (*ptr).id).write(id); + Parker::new_in_place(&raw mut (*ptr).parker); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } + } + + /// Like the public [`park`], but callable on any handle. This is used to + /// allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park(&self) { + unsafe { self.inner.as_ref().parker().park() } + } + + /// Like the public [`park_timeout`], but callable on any handle. This is + /// used to allow parking in TLS destructors. + /// + /// # Safety + /// May only be called from the thread to which this handle belongs. + pub(crate) unsafe fn park_timeout(&self, dur: Duration) { + unsafe { self.inner.as_ref().parker().park_timeout(dur) } + } + + /// Atomically makes the handle's token available if it is not already. + /// + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// static QUEUED: AtomicBool = AtomicBool::new(false); + /// + /// let parked_thread = thread::Builder::new() + /// .spawn(|| { + /// println!("Parking thread"); + /// QUEUED.store(true, Ordering::Release); + /// thread::park(); + /// println!("Thread unparked"); + /// }) + /// .unwrap(); + /// + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// // Wait until the other thread is queued. + /// // This is crucial! It guarantees that the `unpark` below is not consumed + /// // by some other code in the parked thread (e.g. inside `println!`). + /// while !QUEUED.load(Ordering::Acquire) { + /// // Spinning is of course inefficient; in practice, this would more likely be + /// // a dequeue where we have no work to do if there's nobody queued. + /// std::hint::spin_loop(); + /// } + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn unpark(&self) { + self.inner.as_ref().parker().unpark(); + } + + /// Gets the thread's unique identifier. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let other_thread = thread::spawn(|| { + /// thread::current().id() + /// }); + /// + /// let other_thread_id = other_thread.join().unwrap(); + /// assert!(thread::current().id() != other_thread_id); + /// ``` + #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] + pub fn id(&self) -> ThreadId { + self.inner.id + } + + /// Gets the thread's name. + /// + /// For more information about named threads, see + /// [this module-level documentation][naming-threads]. + /// + /// # Examples + /// + /// Threads by default have no name specified: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// assert!(thread::current().name().is_none()); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// Thread with a specified name: + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")) + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + /// + /// [naming-threads]: ./index.html#naming-threads + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn name(&self) -> Option<&str> { + if let Some(name) = &self.inner.name { + Some(name.as_str()) + } else if main_thread::get() == Some(self.inner.id) { + Some("main") + } else { + None + } + } + + /// Consumes the `Thread`, returning a raw pointer. + /// + /// To avoid a memory leak the pointer must be converted + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(thread_raw)] + /// + /// use std::thread::{self, Thread}; + /// + /// let thread = thread::current(); + /// let id = thread.id(); + /// let ptr = Thread::into_raw(thread); + /// unsafe { + /// assert_eq!(Thread::from_raw(ptr).id(), id); + /// } + /// ``` + #[unstable(feature = "thread_raw", issue = "97523")] + pub fn into_raw(self) -> *const () { + // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. + let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; + Arc::into_raw_with_allocator(inner).0 as *const () + } + + /// Constructs a `Thread` from a raw pointer. + /// + /// The raw pointer must have been previously returned + /// by a call to [`Thread::into_raw`]. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead + /// to memory unsafety, even if the returned `Thread` is never + /// accessed. + /// + /// Creating a `Thread` from a pointer other than one returned + /// from [`Thread::into_raw`] is **undefined behavior**. + /// + /// Calling this function twice on the same raw pointer can lead + /// to a double-free if both `Thread` instances are dropped. + #[unstable(feature = "thread_raw", issue = "97523")] + pub unsafe fn from_raw(ptr: *const ()) -> Thread { + // Safety: Upheld by caller. + unsafe { + Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } + } + } + + pub(crate) fn cname(&self) -> Option<&CStr> { + if let Some(name) = &self.inner.name { + Some(name.as_cstr()) + } else if main_thread::get() == Some(self.inner.id) { + Some(c"main") + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle +//////////////////////////////////////////////////////////////////////////////// + +/// A specialized [`Result`] type for threads. +/// +/// Indicates the manner in which a thread exited. +/// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the argument the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the [`Error`](crate::error::Error) trait. +/// +/// Thus, a sensible way to handle a thread panic is to either: +/// +/// 1. propagate the panic with [`std::panic::resume_unwind`] +/// 2. or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match on the `Err` variant and handle the panic in an appropriate way +/// +/// A thread that completes without panicking is considered to exit successfully. +/// +/// # Examples +/// +/// Matching on the result of a joined thread: +/// +/// ```no_run +/// use std::{fs, thread, panic}; +/// +/// fn copy_in_thread() -> thread::Result<()> { +/// thread::spawn(|| { +/// fs::copy("foo.txt", "bar.txt").unwrap(); +/// }).join() +/// } +/// +/// fn main() { +/// match copy_in_thread() { +/// Ok(_) => println!("copy succeeded"), +/// Err(e) => panic::resume_unwind(e), +/// } +/// } +/// ``` +/// +/// [`Result`]: crate::result::Result +/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(search_unbox)] +pub type Result = crate::result::Result>; + +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). +// +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. +struct Packet<'scope, T> { + scope: Option>, + result: UnsafeCell>>, + _marker: PhantomData>, +} + +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} + +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } + // Book-keeping so the scope knows when it's done. + if let Some(scope) = &self.scope { + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. + scope.decrement_num_running_threads(unhandled_panic); + } + } +} + +/// Inner representation for JoinHandle +struct JoinInner<'scope, T> { + native: imp::Thread, + thread: Thread, + packet: Arc>, +} + +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet) + // FIXME(fuzzypixelz): returning an error instead of panicking here + // would require updating the documentation of + // `std::thread::Result`; currently we can return `Err` if and only + // if the thread had panicked. + .expect("threads should not terminate unexpectedly") + .result + .get_mut() + .take() + .unwrap() + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// A `JoinHandle` *detaches* the associated thread when it is dropped, which +/// means that there is no longer any handle to the thread and no way to `join` +/// on it. +/// +/// Due to platform restrictions, it is not possible to [`Clone`] this +/// handle: the ability to join a thread is a uniquely-owned permission. +/// +/// This `struct` is created by the [`thread::spawn`] function and the +/// [`thread::Builder::spawn`] method. +/// +/// # Examples +/// +/// Creation from [`thread::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { +/// // some work here +/// }); +/// ``` +/// +/// Creation from [`thread::Builder::spawn`]: +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { +/// // some work here +/// }).unwrap(); +/// ``` +/// +/// A thread being detached and outliving the thread that spawned it: +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// let original_thread = thread::spawn(|| { +/// let _detached_thread = thread::spawn(|| { +/// // Here we sleep to make sure that the first thread returns before. +/// thread::sleep(Duration::from_millis(10)); +/// // This will be called, even though the JoinHandle is dropped. +/// println!("♫ Still alive ♫"); +/// }); +/// }); +/// +/// original_thread.join().expect("The thread being joined has panicked"); +/// println!("Original thread is joined."); +/// +/// // We make sure that the new thread has time to run, before the main +/// // thread returns. +/// +/// thread::sleep(Duration::from_millis(1000)); +/// ``` +/// +/// [`thread::Builder::spawn`]: Builder::spawn +/// [`thread::spawn`]: spawn +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] +pub struct JoinHandle(JoinInner<'static, T>); + +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Send for JoinHandle {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl Sync for JoinHandle {} + +impl JoinHandle { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// + /// let thread = join_handle.thread(); + /// println!("thread id: {:?}", thread.id()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. In other words, all + /// operations performed by that thread [happen + /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all + /// operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the parameter given + /// to [`panic!`] (though see the Notes below). + /// + /// [`Err`]: crate::result::Result::Err + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { + /// // some work here + /// }).unwrap(); + /// join_handle.join().expect("Couldn't join on the associated thread"); + /// ``` + /// + /// # Notes + /// + /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ + /// code, or a `panic!` in Rust code compiled or linked with a different + /// runtime) unwinds all the way to the thread root, the process may be + /// aborted; see the Notes on [`thread::spawn`]. If the process is not + /// aborted, this function will return a `Result::Err` containing an opaque + /// type. + /// + /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html + /// [`thread::spawn`]: spawn + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread has finished running its main function. + /// + /// `is_finished` supports implementing a non-blocking join operation, by checking + /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To + /// block while waiting on the thread to finish, use [`join`][Self::join]. + /// + /// This might return `true` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + /// However, once this returns `true`, [`join`][Self::join] can be expected + /// to return quickly, without blocking for any significant amount of time. + #[stable(feature = "thread_is_running", since = "1.61.0")] + pub fn is_finished(&self) -> bool { + Arc::strong_count(&self.0.packet) == 1 + } +} + +impl AsInner for JoinHandle { + fn as_inner(&self) -> &imp::Thread { + &self.0.native + } +} + +impl IntoInner for JoinHandle { + fn into_inner(self) -> imp::Thread { + self.0.native + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("JoinHandle").finish_non_exhaustive() + } +} + +fn _assert_sync_and_send() { + fn _assert_both() {} + _assert_both::>(); + _assert_both::(); +} + +/// Returns an estimate of the default amount of parallelism a program should use. +/// +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs a +/// computer has, but it may diverge in various cases. +/// +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. +/// +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. +/// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// +/// The value returned by this function should be considered a simplified +/// approximation of the actual amount of parallelism available at any given +/// time. To get a more detailed or precise overview of the amount of +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. +/// - If the process is in a cgroup v1 cpu controller, this may need to +/// scan mountpoints to find the corresponding cgroup v1 controller, +/// which may take time on systems with large numbers of mountpoints. +/// (This does not apply to cgroup v2, or to processes not in a +/// cgroup.) +/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of +/// threads, `available_parallelism` cannot know how much of that limit a Rust program should +/// take, or know in a reliable and race-free way how much of that limit is already taken. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). +/// +/// # Errors +/// +/// This function will, but is not limited to, return errors in the following +/// cases: +/// +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::{io, thread}; +/// +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub fn available_parallelism() -> io::Result> { + imp::available_parallelism() +} From 8b08da218efb0860d3ba25a0cb9e0952c53a4b2f Mon Sep 17 00:00:00 2001 From: joboet Date: Sun, 9 Nov 2025 19:40:15 +0100 Subject: [PATCH 2/5] std: split up the `thread` module --- library/std/src/thread/builder.rs | 1906 +--------------------- library/std/src/thread/current.rs | 37 +- library/std/src/thread/functions.rs | 1467 +---------------- library/std/src/thread/id.rs | 2040 +---------------------- library/std/src/thread/join_handle.rs | 1983 +--------------------- library/std/src/thread/lifecycle.rs | 2167 ++---------------------- library/std/src/thread/main_thread.rs | 2170 +------------------------ library/std/src/thread/mod.rs | 1953 +--------------------- library/std/src/thread/scoped.rs | 15 +- library/std/src/thread/spawnhook.rs | 2 +- library/std/src/thread/tests.rs | 3 +- library/std/src/thread/thread.rs | 1839 +-------------------- 12 files changed, 302 insertions(+), 15280 deletions(-) diff --git a/library/std/src/thread/builder.rs b/library/std/src/thread/builder.rs index 983d189b07024..6b07a7fd57d3f 100644 --- a/library/std/src/thread/builder.rs +++ b/library/std/src/thread/builder.rs @@ -1,250 +1,6 @@ -//! Native threads. -//! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local - -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; -use crate::any::Any; -use crate::cell::UnsafeCell; -use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; -use crate::pin::Pin; -use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; -use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; -} - -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// +use super::join_handle::JoinHandle; +use super::lifecycle::spawn_unchecked; +use crate::io; /// Thread factory, which can be used in order to configure the properties of /// a new thread. @@ -292,12 +48,12 @@ impl ThreadInit { #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, + /// A name for the thread-to-be, for identification in panic messages + pub(super) name: Option, + /// The size of the stack for the spawned thread in bytes + pub(super) stack_size: Option, + /// Skip running and inheriting the thread spawn hooks + pub(super) no_hooks: bool, } impl Builder { @@ -493,1654 +249,12 @@ impl Builder { #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> where F: FnOnce() -> T, F: Send, T: Send, { let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} - -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } - - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } + Ok(JoinHandle(unsafe { spawn_unchecked(name, stack_size, no_hooks, None, f) }?)) } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } - - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner - } - - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } - } - } -} - -use thread_name_string::ThreadNameString; - -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} - -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); - } - } -} - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} - -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { - fn as_inner(&self) -> &imp::Thread { - &self.0.native - } -} - -impl IntoInner for JoinHandle { - fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() - } -} - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() } diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs index ea0c6c7229fe8..508e35cefe88f 100644 --- a/library/std/src/thread/current.rs +++ b/library/std/src/thread/current.rs @@ -1,6 +1,9 @@ -use super::{Thread, ThreadId, imp}; +use super::id::ThreadId; +use super::main_thread; +use super::thread::Thread; use crate::mem::ManuallyDrop; use crate::ptr; +use crate::sys::thread as imp; use crate::sys::thread_local::local_pointer; const NONE: *mut () = ptr::null_mut(); @@ -184,7 +187,7 @@ pub(crate) fn current_os_id() -> u64 { /// Gets a reference to the handle of the thread that invokes it, if the handle /// has been initialized. -pub(super) fn try_with_current(f: F) -> R +fn try_with_current(f: F) -> R where F: FnOnce(Option<&Thread>) -> R, { @@ -202,6 +205,36 @@ where } } +/// Run a function with the current thread's name. +/// +/// Modulo thread local accesses, this function is safe to call from signal +/// handlers and in similar circumstances where allocations are not possible. +pub(crate) fn with_current_name(f: F) -> R +where + F: FnOnce(Option<&str>) -> R, +{ + try_with_current(|thread| { + let name = if let Some(thread) = thread { + // If there is a current thread handle, try to use the name stored + // there. + thread.name() + } else if let Some(main) = main_thread::get() + && let Some(id) = id::get() + && id == main + { + // The main thread doesn't always have a thread handle, we must + // identify it through its ID instead. The checks are ordered so + // that the current ID is only loaded if it is actually needed, + // since loading it from TLS might need multiple expensive accesses. + Some("main") + } else { + None + }; + + f(name) + }) +} + /// Gets a handle to the thread that invokes it. If the handle stored in thread- /// local storage was already destroyed, this creates a new unnamed temporary /// handle to allow thread parking in nearly all situations. diff --git a/library/std/src/thread/functions.rs b/library/std/src/thread/functions.rs index 983d189b07024..b8f5049de3b1c 100644 --- a/library/std/src/thread/functions.rs +++ b/library/std/src/thread/functions.rs @@ -1,637 +1,13 @@ -//! Native threads. -//! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local +//! Free functions. -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; -use crate::any::Any; -use crate::cell::UnsafeCell; -use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; +use super::builder::Builder; +use super::current::current; +use super::join_handle::JoinHandle; +use crate::mem::forget; use crate::num::NonZero; -use crate::pin::Pin; -use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; -} - -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// +use crate::{io, panicking}; /// Spawns a new thread, returning a [`JoinHandle`] for it. /// @@ -1222,837 +598,6 @@ pub fn park_timeout(dur: Duration) { forget(guard); } -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } - - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } - } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } - - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner - } - - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } - } - } -} - -use thread_name_string::ThreadNameString; - -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} - -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); - } - } -} - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} - -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { - fn as_inner(&self) -> &imp::Thread { - &self.0.native - } -} - -impl IntoInner for JoinHandle { - fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() - } -} - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - /// Returns an estimate of the default amount of parallelism a program should use. /// /// Parallelism is a resource. A given machine provides a certain capacity for diff --git a/library/std/src/thread/id.rs b/library/std/src/thread/id.rs index 983d189b07024..0e528ba25fcb7 100644 --- a/library/std/src/thread/id.rs +++ b/library/std/src/thread/id.rs @@ -1,1230 +1,5 @@ -//! Native threads. -//! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local - -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; -use crate::any::Any; -use crate::cell::UnsafeCell; -use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; -use crate::pin::Pin; -use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; -use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; -} - -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} - -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// +use crate::num::NonZero; +use crate::sync::atomic::{Atomic, Ordering}; /// A unique identifier for a running thread. /// @@ -1264,7 +39,7 @@ impl ThreadId { cfg_select! { target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::AtomicU64; static COUNTER: Atomic = AtomicU64::new(0); @@ -1283,7 +58,7 @@ impl ThreadId { _ => { use crate::cell::SyncUnsafeCell; use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::AtomicBool; use crate::thread::yield_now; // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex @@ -1321,7 +96,7 @@ impl ThreadId { } #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { + pub(super) fn from_u64(v: u64) -> Option { NonZero::new(v).map(ThreadId) } @@ -1339,808 +114,3 @@ impl ThreadId { self.0 } } - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } - - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner - } - - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } - } - } -} - -use thread_name_string::ThreadNameString; - -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} - -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); - } - } -} - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} - -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { - fn as_inner(&self) -> &imp::Thread { - &self.0.native - } -} - -impl IntoInner for JoinHandle { - fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() - } -} - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() -} diff --git a/library/std/src/thread/join_handle.rs b/library/std/src/thread/join_handle.rs index 983d189b07024..04d4733aa6bdf 100644 --- a/library/std/src/thread/join_handle.rs +++ b/library/std/src/thread/join_handle.rs @@ -1,1872 +1,9 @@ -//! Native threads. -//! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local - -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; -use crate::any::Any; -use crate::cell::UnsafeCell; -use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; -use crate::pin::Pin; -use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; -use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; -} - -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} - -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } - - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } - } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } - - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner - } - - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } - } - } -} - -use thread_name_string::ThreadNameString; - -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} - -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); - } - } -} - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} +use super::Result; +use super::lifecycle::JoinInner; +use super::thread::Thread; +use crate::fmt; +use crate::sys::thread as imp; +use crate::sys_common::{AsInner, IntoInner}; /// An owned permission to join on a thread (block on its termination). /// @@ -1932,7 +69,7 @@ impl<'scope, T> JoinInner<'scope, T> { /// [`thread::spawn`]: spawn #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); +pub struct JoinHandle(pub(super) JoinInner<'static, T>); #[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] unsafe impl Send for JoinHandle {} @@ -1959,7 +96,7 @@ impl JoinHandle { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub fn thread(&self) -> &Thread { - &self.0.thread + self.0.thread() } /// Waits for the associated thread to finish. @@ -2024,19 +161,19 @@ impl JoinHandle { /// to return quickly, without blocking for any significant amount of time. #[stable(feature = "thread_is_running", since = "1.61.0")] pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 + self.0.is_finished() } } impl AsInner for JoinHandle { fn as_inner(&self) -> &imp::Thread { - &self.0.native + self.0.as_inner() } } impl IntoInner for JoinHandle { fn into_inner(self) -> imp::Thread { - self.0.native + self.0.into_inner() } } @@ -2046,101 +183,3 @@ impl fmt::Debug for JoinHandle { f.debug_struct("JoinHandle").finish_non_exhaustive() } } - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() -} diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs index 983d189b07024..119322b909b52 100644 --- a/library/std/src/thread/lifecycle.rs +++ b/library/std/src/thread/lifecycle.rs @@ -1,215 +1,139 @@ -//! Native threads. -//! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local +//! The inner logic for thread spawning and joining. -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; -use crate::any::Any; +use super::current::set_current; +use super::id::ThreadId; +use super::scoped::ScopeData; +use super::thread::Thread; +use super::{Result, spawnhook}; use crate::cell::UnsafeCell; -use crate::ffi::CStr; use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; -use crate::pin::Pin; +use crate::mem::{ManuallyDrop, MaybeUninit}; use crate::sync::Arc; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; use crate::sys::thread as imp; use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; +use crate::{env, io, panic}; -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub(super) unsafe fn spawn_unchecked<'scope, F, T>( + name: Option, + stack_size: Option, + no_hooks: bool, + scope_data: Option>, + f: F, +) -> io::Result> +where + F: FnOnce() -> T, + F: Send, + T: Send, +{ + let stack_size = stack_size.unwrap_or_else(|| { + static MIN: Atomic = AtomicUsize::new(0); -#[macro_use] -mod local; + match MIN.load(Ordering::Relaxed) { + 0 => {} + n => return n - 1, + } -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; + let amt = env::var_os("RUST_MIN_STACK") + .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) + .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); + + // 0 is our sentinel value, so ensure that we'll never see 0 after + // initialization has run + MIN.store(amt + 1, Ordering::Relaxed); + amt + }); + + let id = ThreadId::new(); + let thread = Thread::new(id, name); + + let hooks = if no_hooks { + spawnhook::ChildSpawnHooks::default() + } else { + spawnhook::run_spawn_hooks(&thread) + }; + + let my_packet: Arc> = + Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None), _marker: PhantomData }); + let their_packet = my_packet.clone(); + + // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + // To prevent leaks we use a wrapper that drops its contents. + #[repr(transparent)] + struct MaybeDangling(MaybeUninit); + impl MaybeDangling { + fn new(x: T) -> Self { + MaybeDangling(MaybeUninit::new(x)) + } + fn into_inner(self) -> T { + // Make sure we don't drop. + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } + } + } + impl Drop for MaybeDangling { + fn drop(&mut self) { + // SAFETY: we are always initialized. + unsafe { self.0.assume_init_drop() }; + } + } -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; + let f = MaybeDangling::new(f); + + // The entrypoint of the Rust thread, after platform-specific thread + // initialization is done. + let rust_start = move || { + let f = f.into_inner(); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); + crate::sys::backtrace::__rust_begin_short_backtrace(f) + })); + // SAFETY: `their_packet` as been built just above and moved by the + // closure (it is an Arc<...>) and `my_packet` will be stored in the + // same `JoinInner` as this closure meaning the mutation will be + // safe (not modify it and affect a value far away). + unsafe { *their_packet.result.get() = Some(try_result) }; + // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that + // will call `decrement_num_running_threads` and therefore signal that this thread is + // done. + drop(their_packet); + // Here, the lifetime `'scope` can end. `main` keeps running for a bit + // after that before returning itself. + }; + + if let Some(scope_data) = &my_packet.scope { + scope_data.increment_num_running_threads(); + } + + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. + let rust_start = unsafe { + Box::from_raw(Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static)) + }; + + let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); + + Ok(JoinInner { + // SAFETY: + // + // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed + // through FFI or otherwise used with low-level threading primitives that have no + // notion of or way to enforce lifetimes. + // + // As mentioned in the `Safety` section of this function's documentation, the caller of + // this function needs to guarantee that the passed-in lifetime is sufficiently long + // for the lifetime of the thread. + // + // Similarly, the `sys` implementation must guarantee that no references to the closure + // exist after the thread has terminated, which is signaled by `Thread::join` + // returning. + native: unsafe { imp::Thread::new(stack_size, init)? }, + thread, + packet: my_packet, + }) } /// The data passed to the spawned thread for thread initialization. Any thread @@ -242,1558 +166,6 @@ impl ThreadInit { } } -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} - -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } - - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } - } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } - - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner - } - - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } - } - } -} - -use thread_name_string::ThreadNameString; - -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - // This packet is used to communicate the return value between the spawned // thread and the rest of the program. It is shared through an `Arc` and // there's no need for a mutex here because synchronization happens with `join()` @@ -1802,9 +174,9 @@ pub type Result = crate::result::Result>; // An Arc to the packet is stored into a `JoinInner` which in turns is placed // in `JoinHandle`. struct Packet<'scope, T> { - scope: Option>, + scope: Option>, result: UnsafeCell>>, - _marker: PhantomData>, + _marker: PhantomData>, } // Due to the usage of `UnsafeCell` we need to manually implement Sync. @@ -1846,14 +218,22 @@ impl<'scope, T> Drop for Packet<'scope, T> { } /// Inner representation for JoinHandle -struct JoinInner<'scope, T> { +pub(super) struct JoinInner<'scope, T> { native: imp::Thread, thread: Thread, packet: Arc>, } impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { + pub(super) fn is_finished(&self) -> bool { + Arc::strong_count(&self.packet) == 1 + } + + pub(super) fn thread(&self) -> &Thread { + &self.thread + } + + pub(super) fn join(mut self) -> Result { self.native.join(); Arc::get_mut(&mut self.packet) // FIXME(fuzzypixelz): returning an error instead of panicking here @@ -1868,279 +248,14 @@ impl<'scope, T> JoinInner<'scope, T> { } } -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { +impl AsInner for JoinInner<'static, T> { fn as_inner(&self) -> &imp::Thread { - &self.0.native + &self.native } } -impl IntoInner for JoinHandle { +impl IntoInner for JoinInner<'static, T> { fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() + self.native } } - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() -} diff --git a/library/std/src/thread/main_thread.rs b/library/std/src/thread/main_thread.rs index 983d189b07024..394074a593674 100644 --- a/library/std/src/thread/main_thread.rs +++ b/library/std/src/thread/main_thread.rs @@ -1,2146 +1,56 @@ -//! Native threads. +//! Store the ID of the main thread. //! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local - -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; -use crate::any::Any; -use crate::cell::UnsafeCell; -use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; -use crate::pin::Pin; -use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; -use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; -} - -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} +//! The thread handle for the main thread is created lazily, and this might even +//! happen pre-main. Since not every platform has a way to identify the main +//! thread when that happens – macOS's `pthread_main_np` function being a notable +//! exception – we cannot assign it the right name right then. Instead, in our +//! runtime startup code, we remember the thread ID of the main thread (through +//! this modules `set` function) and use it to identify the main thread from then +//! on. This works reliably and has the additional advantage that we can report +//! the right thread name on main even after the thread handle has been destroyed. +//! Note however that this also means that the name reported in pre-main functions +//! will be incorrect, but that's just something we have to live with. -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } +cfg_select! { + target_has_atomic = "64" => { + use super::id::ThreadId; + use crate::sync::atomic::{Atomic, AtomicU64}; + use crate::sync::atomic::Ordering::Relaxed; - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } - } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } + static MAIN: Atomic = AtomicU64::new(0); - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner + pub(super) fn get() -> Option { + ThreadId::from_u64(MAIN.load(Relaxed)) } - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + MAIN.store(id.as_u64().get(), Relaxed) } } -} - -use thread_name_string::ThreadNameString; + _ => { + use super::id::ThreadId; + use crate::mem::MaybeUninit; + use crate::sync::atomic::{Atomic, AtomicBool}; + use crate::sync::atomic::Ordering::{Acquire, Release}; -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; + static INIT: Atomic = AtomicBool::new(false); + static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) + pub(super) fn get() -> Option { + if INIT.load(Acquire) { + Some(unsafe { MAIN.assume_init() }) + } else { + None } } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); + /// # Safety + /// May only be called once. + pub(crate) unsafe fn set(id: ThreadId) { + unsafe { MAIN = MaybeUninit::new(id) }; + INIT.store(true, Release); } } } - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} - -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { - fn as_inner(&self) -> &imp::Thread { - &self.0.native - } -} - -impl IntoInner for JoinHandle { - fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() - } -} - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() -} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 983d189b07024..251a2feec0077 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -155,54 +155,56 @@ // Under `test`, `__FastLocalKeyInner` seems unused. #![cfg_attr(test, allow(dead_code))] -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -use crate::alloc::System; use crate::any::Any; -use crate::cell::UnsafeCell; -use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; -use crate::pin::Pin; -use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sys::sync::Parker; -use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; -#[stable(feature = "scoped_threads", since = "1.63.0")] +#[macro_use] +mod local; +mod builder; +mod current; +mod functions; +mod id; +mod join_handle; +mod lifecycle; mod scoped; +mod spawnhook; +mod thread; -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; +pub(crate) mod main_thread; -mod current; +#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] +mod tests; +#[stable(feature = "rust1", since = "1.0.0")] +pub use builder::Builder; #[stable(feature = "rust1", since = "1.0.0")] pub use current::current; #[unstable(feature = "current_thread_id", issue = "147194")] pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - +pub(crate) use current::{current_or_unnamed, current_os_id, drop_current, with_current_name}; +#[stable(feature = "available_parallelism", since = "1.59.0")] +pub use functions::available_parallelism; +#[stable(feature = "park_timeout", since = "1.4.0")] +pub use functions::park_timeout; +#[stable(feature = "thread_sleep", since = "1.4.0")] +pub use functions::sleep; +#[unstable(feature = "thread_sleep_until", issue = "113752")] +pub use functions::sleep_until; +#[expect(deprecated)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use functions::{panicking, park, park_timeout_ms, sleep_ms, spawn, yield_now}; +#[stable(feature = "thread_id", since = "1.19.0")] +pub use id::ThreadId; +#[stable(feature = "rust1", since = "1.0.0")] +pub use join_handle::JoinHandle; +pub(crate) use lifecycle::ThreadInit; +#[stable(feature = "rust1", since = "1.0.0")] +pub use local::{AccessError, LocalKey}; +#[stable(feature = "scoped_threads", since = "1.63.0")] +pub use scoped::{Scope, ScopedJoinHandle, scope}; #[unstable(feature = "thread_spawn_hook", issue = "132951")] pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - #[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; +pub use thread::Thread; // Implementation details used by the thread_local!{} macro. #[doc(hidden)] @@ -212,1542 +214,6 @@ pub mod local_impl { pub use crate::sys::thread_local::*; } -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} - -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } - - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } - } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// - -// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. -mod thread_name_string { - use crate::ffi::{CStr, CString}; - use crate::str; - - /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. - pub(crate) struct ThreadNameString { - inner: CString, - } - - impl From for ThreadNameString { - fn from(s: String) -> Self { - Self { - inner: CString::new(s).expect("thread name may not contain interior null bytes"), - } - } - } - - impl ThreadNameString { - pub fn as_cstr(&self) -> &CStr { - &self.inner - } - - pub fn as_str(&self) -> &str { - // SAFETY: `ThreadNameString` is guaranteed to be UTF-8. - unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) } - } - } -} - -use thread_name_string::ThreadNameString; - -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - -/// The internal representation of a `Thread` handle -/// -/// We explicitly set the alignment for our guarantee in Thread::into_raw. This -/// allows applications to stuff extra metadata bits into the alignment, which -/// can be rather useful when working with atomics. -#[repr(align(8))] -struct Inner { - name: Option, - id: ThreadId, - parker: Parker, -} - -impl Inner { - fn parker(self: Pin<&Self>) -> Pin<&Parker> { - unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } - } -} - -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -/// A handle to a thread. -/// -/// Threads are represented via the `Thread` type, which you can get in one of -/// two ways: -/// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. -/// * By requesting the current thread, using the [`thread::current`] function. -/// -/// The [`thread::current`] function is available even for threads not spawned -/// by the APIs of this module. -/// -/// There is usually no need to create a `Thread` struct yourself, one -/// should instead use a function like `spawn` to create new threads, see the -/// docs of [`Builder`] and [`spawn`] for more details. -/// -/// [`thread::current`]: current::current -pub struct Thread { - // We use the System allocator such that creating or dropping this handle - // does not interfere with a potential Global allocator using thread-local - // storage. - inner: Pin>, -} - -impl Thread { - pub(crate) fn new(id: ThreadId, name: Option) -> Thread { - let name = name.map(ThreadNameString::from); - - // We have to use `unsafe` here to construct the `Parker` in-place, - // which is required for the UNIX implementation. - // - // SAFETY: We pin the Arc immediately after creation, so its address never - // changes. - let inner = unsafe { - let mut arc = Arc::::new_uninit_in(System); - let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); - (&raw mut (*ptr).name).write(name); - (&raw mut (*ptr).id).write(id); - Parker::new_in_place(&raw mut (*ptr).parker); - Pin::new_unchecked(arc.assume_init()) - }; - - Thread { inner } - } - - /// Like the public [`park`], but callable on any handle. This is used to - /// allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park(&self) { - unsafe { self.inner.as_ref().parker().park() } - } - - /// Like the public [`park_timeout`], but callable on any handle. This is - /// used to allow parking in TLS destructors. - /// - /// # Safety - /// May only be called from the thread to which this handle belongs. - pub(crate) unsafe fn park_timeout(&self, dur: Duration) { - unsafe { self.inner.as_ref().parker().park_timeout(dur) } - } - - /// Atomically makes the handle's token available if it is not already. - /// - /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. - /// - /// See the [park documentation][park] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// use std::time::Duration; - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// static QUEUED: AtomicBool = AtomicBool::new(false); - /// - /// let parked_thread = thread::Builder::new() - /// .spawn(|| { - /// println!("Parking thread"); - /// QUEUED.store(true, Ordering::Release); - /// thread::park(); - /// println!("Thread unparked"); - /// }) - /// .unwrap(); - /// - /// // Let some time pass for the thread to be spawned. - /// thread::sleep(Duration::from_millis(10)); - /// - /// // Wait until the other thread is queued. - /// // This is crucial! It guarantees that the `unpark` below is not consumed - /// // by some other code in the parked thread (e.g. inside `println!`). - /// while !QUEUED.load(Ordering::Acquire) { - /// // Spinning is of course inefficient; in practice, this would more likely be - /// // a dequeue where we have no work to do if there's nobody queued. - /// std::hint::spin_loop(); - /// } - /// - /// println!("Unpark the thread"); - /// parked_thread.thread().unpark(); - /// - /// parked_thread.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn unpark(&self) { - self.inner.as_ref().parker().unpark(); - } - - /// Gets the thread's unique identifier. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let other_thread = thread::spawn(|| { - /// thread::current().id() - /// }); - /// - /// let other_thread_id = other_thread.join().unwrap(); - /// assert!(thread::current().id() != other_thread_id); - /// ``` - #[stable(feature = "thread_id", since = "1.19.0")] - #[must_use] - pub fn id(&self) -> ThreadId { - self.inner.id - } - - /// Gets the thread's name. - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// Threads by default have no name specified: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// assert!(thread::current().name().is_none()); - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// Thread with a specified name: - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn name(&self) -> Option<&str> { - if let Some(name) = &self.inner.name { - Some(name.as_str()) - } else if main_thread::get() == Some(self.inner.id) { - Some("main") - } else { - None - } - } - - /// Consumes the `Thread`, returning a raw pointer. - /// - /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. The pointer is - /// guaranteed to be aligned to at least 8 bytes. - /// - /// # Examples - /// - /// ``` - /// #![feature(thread_raw)] - /// - /// use std::thread::{self, Thread}; - /// - /// let thread = thread::current(); - /// let id = thread.id(); - /// let ptr = Thread::into_raw(thread); - /// unsafe { - /// assert_eq!(Thread::from_raw(ptr).id(), id); - /// } - /// ``` - #[unstable(feature = "thread_raw", issue = "97523")] - pub fn into_raw(self) -> *const () { - // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant. - let inner = unsafe { Pin::into_inner_unchecked(self.inner) }; - Arc::into_raw_with_allocator(inner).0 as *const () - } - - /// Constructs a `Thread` from a raw pointer. - /// - /// The raw pointer must have been previously returned - /// by a call to [`Thread::into_raw`]. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead - /// to memory unsafety, even if the returned `Thread` is never - /// accessed. - /// - /// Creating a `Thread` from a pointer other than one returned - /// from [`Thread::into_raw`] is **undefined behavior**. - /// - /// Calling this function twice on the same raw pointer can lead - /// to a double-free if both `Thread` instances are dropped. - #[unstable(feature = "thread_raw", issue = "97523")] - pub unsafe fn from_raw(ptr: *const ()) -> Thread { - // Safety: Upheld by caller. - unsafe { - Thread { inner: Pin::new_unchecked(Arc::from_raw_in(ptr as *const Inner, System)) } - } - } - - pub(crate) fn cname(&self) -> Option<&CStr> { - if let Some(name) = &self.inner.name { - Some(name.as_cstr()) - } else if main_thread::get() == Some(self.inner.id) { - Some(c"main") - } else { - None - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Thread { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread") - .field("id", &self.id()) - .field("name", &self.name()) - .finish_non_exhaustive() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - /// A specialized [`Result`] type for threads. /// /// Indicates the manner in which a thread exited. @@ -1794,353 +260,8 @@ impl fmt::Debug for Thread { #[doc(search_unbox)] pub type Result = crate::result::Result>; -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} - -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); - } - } -} - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} - -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { - fn as_inner(&self) -> &imp::Thread { - &self.0.native - } -} - -impl IntoInner for JoinHandle { - fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() - } -} - fn _assert_sync_and_send() { fn _assert_both() {} _assert_both::>(); _assert_both::(); } - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() -} diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 75a5303fc321a..301f5e949cac3 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -1,4 +1,8 @@ -use super::{Builder, JoinInner, Result, Thread, current_or_unnamed}; +use super::Result; +use super::builder::Builder; +use super::current::current_or_unnamed; +use super::lifecycle::{JoinInner, spawn_unchecked}; +use super::thread::Thread; use crate::marker::PhantomData; use crate::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; use crate::sync::Arc; @@ -257,7 +261,10 @@ impl Builder { F: FnOnce() -> T + Send + 'scope, T: Send + 'scope, { - Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(scope.data.clone())) }?)) + let Builder { name, stack_size, no_hooks } = self; + Ok(ScopedJoinHandle(unsafe { + spawn_unchecked(name, stack_size, no_hooks, Some(scope.data.clone()), f) + }?)) } } @@ -279,7 +286,7 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> { #[must_use] #[stable(feature = "scoped_threads", since = "1.63.0")] pub fn thread(&self) -> &Thread { - &self.0.thread + self.0.thread() } /// Waits for the associated thread to finish. @@ -325,7 +332,7 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> { /// to return quickly, without blocking for any significant amount of time. #[stable(feature = "scoped_threads", since = "1.63.0")] pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 + self.0.is_finished() } } diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs index c8a7bcf55c14e..254793ac33d08 100644 --- a/library/std/src/thread/spawnhook.rs +++ b/library/std/src/thread/spawnhook.rs @@ -1,7 +1,7 @@ +use super::thread::Thread; use crate::cell::Cell; use crate::iter; use crate::sync::Arc; -use crate::thread::Thread; crate::thread_local! { /// A thread local linked list of spawn hooks. diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 2117f5f93ce26..4b934c039a36f 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -1,11 +1,10 @@ -use super::Builder; use crate::any::Any; use crate::panic::panic_any; use crate::result; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::mpsc::{Sender, channel}; use crate::sync::{Arc, Barrier}; -use crate::thread::{self, Scope, ThreadId}; +use crate::thread::{self, Builder, Scope, ThreadId}; use crate::time::{Duration, Instant}; // !!! These tests are dangerous. If something is buggy, they will hang, !!! diff --git a/library/std/src/thread/thread.rs b/library/std/src/thread/thread.rs index 983d189b07024..7edadc041c906 100644 --- a/library/std/src/thread/thread.rs +++ b/library/std/src/thread/thread.rs @@ -1,1348 +1,12 @@ -//! Native threads. -//! -//! ## The threading model -//! -//! An executing Rust program consists of a collection of native OS threads, -//! each with their own stack and local state. Threads can be named, and -//! provide some built-in support for low-level synchronization. -//! -//! Communication between threads can be done through -//! [channels], Rust's message-passing types, along with [other forms of thread -//! synchronization](../../std/sync/index.html) and shared-memory data -//! structures. In particular, types that are guaranteed to be -//! threadsafe are easily shared between threads using the -//! atomically-reference-counted container, [`Arc`]. -//! -//! Fatal logic errors in Rust cause *thread panic*, during which -//! a thread will unwind the stack, running destructors and freeing -//! owned resources. While not meant as a 'try/catch' mechanism, panics -//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with -//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered -//! from, or alternatively be resumed with -//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic -//! is not caught the thread will exit, but the panic may optionally be -//! detected from a different thread with [`join`]. If the main thread panics -//! without the panic being caught, the application will exit with a -//! non-zero exit code. -//! -//! When the main thread of a Rust program terminates, the entire program shuts -//! down, even if other threads are still running. However, this module provides -//! convenient facilities for automatically waiting for the termination of a -//! thread (i.e., join). -//! -//! ## Spawning a thread -//! -//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: -//! -//! ```rust -//! use std::thread; -//! -//! thread::spawn(move || { -//! // some work here -//! }); -//! ``` -//! -//! In this example, the spawned thread is "detached," which means that there is -//! no way for the program to learn when the spawned thread completes or otherwise -//! terminates. -//! -//! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] -//! object that is returned by the call to [`spawn`], which provides -//! a `join` method that allows the caller to wait for the completion of the -//! spawned thread: -//! -//! ```rust -//! use std::thread; -//! -//! let thread_join_handle = thread::spawn(move || { -//! // some work here -//! }); -//! // some work here -//! let res = thread_join_handle.join(); -//! ``` -//! -//! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final -//! value produced by the spawned thread, or [`Err`] of the value given to -//! a call to [`panic!`] if the thread panicked. -//! -//! Note that there is no parent/child relationship between a thread that spawns a -//! new thread and the thread being spawned. In particular, the spawned thread may or -//! may not outlive the spawning thread, unless the spawning thread is the main thread. -//! -//! ## Configuring threads -//! -//! A new thread can be configured before it is spawned via the [`Builder`] type, -//! which currently allows you to set the name and stack size for the thread: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! use std::thread; -//! -//! thread::Builder::new().name("thread1".to_string()).spawn(move || { -//! println!("Hello, world!"); -//! }); -//! ``` -//! -//! ## The `Thread` type -//! -//! Threads are represented via the [`Thread`] type, which you can get in one of -//! two ways: -//! -//! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current`] function. -//! -//! The [`thread::current`] function is available even for threads not spawned -//! by the APIs of this module. -//! -//! ## Thread-local storage -//! -//! This module also provides an implementation of thread-local storage for Rust -//! programs. Thread-local storage is a method of storing data into a global -//! variable that each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! A thread-local key owns the value it contains and will destroy the value when the -//! thread exits. It is created with the [`thread_local!`] macro and can contain any -//! value that is `'static` (no borrowed pointers). It provides an accessor function, -//! [`with`], that yields a shared reference to the value to the specified -//! closure. Thread-local keys allow only shared access to values, as there would be no -//! way to guarantee uniqueness if mutable borrows were allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! [`Cell`] or [`RefCell`] types. -//! -//! ## Naming threads -//! -//! Threads are able to have associated names for identification purposes. By default, spawned -//! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass -//! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the -//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: -//! -//! * If a panic occurs in a named thread, the thread name will be printed in the panic message. -//! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in -//! unix-like platforms). -//! -//! ## Stack size -//! -//! The default stack size is platform-dependent and subject to change. -//! Currently, it is 2 MiB on all Tier-1 platforms. -//! -//! There are two ways to manually specify the stack size for spawned threads: -//! -//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. -//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that -//! changes to `RUST_MIN_STACK` may be ignored after program start. -//! -//! Note that the stack size of the main thread is *not* determined by Rust. -//! -//! [channels]: crate::sync::mpsc -//! [`join`]: JoinHandle::join -//! [`Result`]: crate::result::Result -//! [`Ok`]: crate::result::Result::Ok -//! [`Err`]: crate::result::Result::Err -//! [`thread::current`]: current::current -//! [`thread::Result`]: Result -//! [`unpark`]: Thread::unpark -//! [`thread::park_timeout`]: park_timeout -//! [`Cell`]: crate::cell::Cell -//! [`RefCell`]: crate::cell::RefCell -//! [`with`]: LocalKey::with -//! [`thread_local!`]: crate::thread_local - -#![stable(feature = "rust1", since = "1.0.0")] -#![deny(unsafe_op_in_unsafe_fn)] -// Under `test`, `__FastLocalKeyInner` seems unused. -#![cfg_attr(test, allow(dead_code))] - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - +use super::id::ThreadId; +use super::main_thread; use crate::alloc::System; -use crate::any::Any; -use crate::cell::UnsafeCell; use crate::ffi::CStr; -use crate::marker::PhantomData; -use crate::mem::{self, ManuallyDrop, forget}; -use crate::num::NonZero; +use crate::fmt; use crate::pin::Pin; use crate::sync::Arc; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::sync::Parker; -use crate::sys::thread as imp; -use crate::sys_common::{AsInner, IntoInner}; -use crate::time::{Duration, Instant}; -use crate::{env, fmt, io, panic, panicking, str}; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -mod scoped; - -#[stable(feature = "scoped_threads", since = "1.63.0")] -pub use scoped::{Scope, ScopedJoinHandle, scope}; - -mod current; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use current::current; -#[unstable(feature = "current_thread_id", issue = "147194")] -pub use current::current_id; -pub(crate) use current::{current_or_unnamed, current_os_id, drop_current}; -use current::{set_current, try_with_current}; - -mod spawnhook; - -#[unstable(feature = "thread_spawn_hook", issue = "132951")] -pub use spawnhook::add_spawn_hook; - -//////////////////////////////////////////////////////////////////////////////// -// Thread-local storage -//////////////////////////////////////////////////////////////////////////////// - -#[macro_use] -mod local; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Implementation details used by the thread_local!{} macro. -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", issue = "none")] -pub mod local_impl { - pub use super::local::thread_local_process_attrs; - pub use crate::sys::thread_local::*; -} - -/// The data passed to the spawned thread for thread initialization. Any thread -/// implementation should start a new thread by calling .init() on this before -/// doing anything else to ensure the current thread is properly initialized and -/// the global allocator works. -pub(crate) struct ThreadInit { - pub handle: Thread, - pub rust_start: Box, -} - -impl ThreadInit { - /// Initialize the 'current thread' mechanism on this thread, returning the - /// Rust entry point. - pub fn init(self: Box) -> Box { - // Set the current thread before any (de)allocations on the global allocator occur, - // so that it may call std::thread::current() in its implementation. This is also - // why we take Box, to ensure the Box is not destroyed until after this point. - // Cloning the handle does not invoke the global allocator, it is an Arc. - if let Err(_thread) = set_current(self.handle.clone()) { - // The current thread should not have set yet. Use an abort to save binary size (see #123356). - rtabort!("current thread handle already set during thread spawn"); - } - - if let Some(name) = self.handle.cname() { - imp::set_name(name); - } - - self.rust_start - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Builder -//////////////////////////////////////////////////////////////////////////////// - -/// Thread factory, which can be used in order to configure the properties of -/// a new thread. -/// -/// Methods can be chained on it in order to configure it. -/// -/// The two configurations available are: -/// -/// - [`name`]: specifies an [associated name for the thread][naming-threads] -/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] -/// -/// The [`spawn`] method will take ownership of the builder and create an -/// [`io::Result`] to the thread handle with the given configuration. -/// -/// The [`thread::spawn`] free function uses a `Builder` with default -/// configuration and [`unwrap`]s its return value. -/// -/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want -/// to recover from a failure to launch a thread, indeed the free function will -/// panic where the `Builder` method will return a [`io::Result`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let handler = builder.spawn(|| { -/// // thread code -/// }).unwrap(); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// [`stack_size`]: Builder::stack_size -/// [`name`]: Builder::name -/// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -/// [`io::Result`]: crate::io::Result -/// [`unwrap`]: crate::result::Result::unwrap -/// [naming-threads]: ./index.html#naming-threads -/// [stack-size]: ./index.html#stack-size -#[must_use = "must eventually spawn the thread"] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Builder { - // A name for the thread-to-be, for identification in panic messages - name: Option, - // The size of the stack for the spawned thread in bytes - stack_size: Option, - // Skip running and inheriting the thread spawn hooks - no_hooks: bool, -} - -impl Builder { - /// Generates the base configuration for spawning a thread, from which - /// configuration methods can be chained. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()) - /// .stack_size(32 * 1024); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Builder { - Builder { name: None, stack_size: None, no_hooks: false } - } - - /// Names the thread-to-be. Currently the name is used for identification - /// only in panic messages. - /// - /// The name must not contain null bytes (`\0`). - /// - /// For more information about named threads, see - /// [this module-level documentation][naming-threads]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new() - /// .name("foo".into()); - /// - /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")) - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - /// - /// [naming-threads]: ./index.html#naming-threads - #[stable(feature = "rust1", since = "1.0.0")] - pub fn name(mut self, name: String) -> Builder { - self.name = Some(name); - self - } - - /// Sets the size of the stack (in bytes) for the new thread. - /// - /// The actual stack size may be greater than this value if - /// the platform specifies a minimal stack size. - /// - /// For more information about the stack size for threads, see - /// [this module-level documentation][stack-size]. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new().stack_size(32 * 1024); - /// ``` - /// - /// [stack-size]: ./index.html#stack-size - #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: usize) -> Builder { - self.stack_size = Some(size); - self - } - - /// Disables running and inheriting [spawn hooks](add_spawn_hook). - /// - /// Use this if the parent thread is in no way relevant for the child thread. - /// For example, when lazily spawning threads for a thread pool. - #[unstable(feature = "thread_spawn_hook", issue = "132951")] - pub fn no_hooks(mut self) -> Builder { - self.no_hooks = true; - self - } - - /// Spawns a new thread by taking ownership of the `Builder`, and returns an - /// [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// [`io::Result`]: crate::io::Result - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let handler = builder.spawn(|| { - /// // thread code - /// }).unwrap(); - /// - /// handler.join().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn spawn(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, - { - unsafe { self.spawn_unchecked(f) } - } - - /// Spawns a new thread without any lifetime restrictions by taking ownership - /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. - /// - /// The spawned thread may outlive the caller (unless the caller thread - /// is the main thread; the whole process is terminated when the main - /// thread finishes). The join handle can be used to block on - /// termination of the spawned thread, including recovering its panics. - /// - /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], - /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. - /// - /// # Errors - /// - /// Unlike the [`spawn`] free function, this method yields an - /// [`io::Result`] to capture any failure to create the thread at - /// the OS level. - /// - /// # Panics - /// - /// Panics if a thread name was set and it contained null bytes. - /// - /// # Safety - /// - /// The caller has to ensure that the spawned thread does not outlive any - /// references in the supplied thread closure and its return type. - /// This can be guaranteed in two ways: - /// - /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced - /// data is dropped - /// - use only types with `'static` lifetime bounds, i.e., those with no or only - /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let x = 1; - /// let thread_x = &x; - /// - /// let handler = unsafe { - /// builder.spawn_unchecked(move || { - /// println!("x = {}", *thread_x); - /// }).unwrap() - /// }; - /// - /// // caller has to ensure `join()` is called, otherwise - /// // it is possible to access freed memory if `x` gets - /// // dropped before the thread closure is executed! - /// handler.join().unwrap(); - /// ``` - /// - /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) - } - - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - unsafe fn spawn_unchecked_<'scope, F, T>( - self, - f: F, - scope_data: Option>, - ) -> io::Result> - where - F: FnOnce() -> T, - F: Send, - T: Send, - { - let Builder { name, stack_size, no_hooks } = self; - - let stack_size = stack_size.unwrap_or_else(|| { - static MIN: Atomic = AtomicUsize::new(0); - - match MIN.load(Ordering::Relaxed) { - 0 => {} - n => return n - 1, - } - - let amt = env::var_os("RUST_MIN_STACK") - .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) - .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE); - - // 0 is our sentinel value, so ensure that we'll never see 0 after - // initialization has run - MIN.store(amt + 1, Ordering::Relaxed); - amt - }); - - let id = ThreadId::new(); - let thread = Thread::new(id, name); - - let hooks = if no_hooks { - spawnhook::ChildSpawnHooks::default() - } else { - spawnhook::run_spawn_hooks(&thread) - }; - - let my_packet: Arc> = Arc::new(Packet { - scope: scope_data, - result: UnsafeCell::new(None), - _marker: PhantomData, - }); - let their_packet = my_packet.clone(); - - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(mem::MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(mem::MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - - let f = MaybeDangling::new(f); - - // The entrypoint of the Rust thread, after platform-specific thread - // initialization is done. - let rust_start = move || { - let f = f.into_inner(); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run()); - crate::sys::backtrace::__rust_begin_short_backtrace(f) - })); - // SAFETY: `their_packet` as been built just above and moved by the - // closure (it is an Arc<...>) and `my_packet` will be stored in the - // same `JoinInner` as this closure meaning the mutation will be - // safe (not modify it and affect a value far away). - unsafe { *their_packet.result.get() = Some(try_result) }; - // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that - // will call `decrement_num_running_threads` and therefore signal that this thread is - // done. - drop(their_packet); - // Here, the lifetime `'scope` can end. `main` keeps running for a bit - // after that before returning itself. - }; - - if let Some(scope_data) = &my_packet.scope { - scope_data.increment_num_running_threads(); - } - - // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the - // lifetime change is justified. - let rust_start = unsafe { - Box::from_raw( - Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static) - ) - }; - - let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); - - Ok(JoinInner { - // SAFETY: - // - // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed - // through FFI or otherwise used with low-level threading primitives that have no - // notion of or way to enforce lifetimes. - // - // As mentioned in the `Safety` section of this function's documentation, the caller of - // this function needs to guarantee that the passed-in lifetime is sufficiently long - // for the lifetime of the thread. - // - // Similarly, the `sys` implementation must guarantee that no references to the closure - // exist after the thread has terminated, which is signaled by `Thread::join` - // returning. - native: unsafe { imp::Thread::new(stack_size, init)? }, - thread, - packet: my_packet, - }) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Free functions -//////////////////////////////////////////////////////////////////////////////// - -/// Spawns a new thread, returning a [`JoinHandle`] for it. -/// -/// The join handle provides a [`join`] method that can be used to join the spawned -/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing -/// the argument given to [`panic!`]. -/// -/// If the join handle is dropped, the spawned thread will implicitly be *detached*. -/// In this case, the spawned thread may no longer be joined. -/// (It is the responsibility of the program to either eventually join threads it -/// creates or detach them; otherwise, a resource leak will result.) -/// -/// This function creates a thread with the default parameters of [`Builder`]. -/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. -/// -/// As you can see in the signature of `spawn` there are two constraints on -/// both the closure given to `spawn` and its return value, let's explain them: -/// -/// - The `'static` constraint means that the closure and its return value -/// must have a lifetime of the whole program execution. The reason for this -/// is that threads can outlive the lifetime they have been created in. -/// -/// Indeed if the thread, and by extension its return value, can outlive their -/// caller, we need to make sure that they will be valid afterwards, and since -/// we *can't* know when it will return we need to have them valid as long as -/// possible, that is until the end of the program, hence the `'static` -/// lifetime. -/// - The [`Send`] constraint is because the closure will need to be passed -/// *by value* from the thread where it is spawned to the new thread. Its -/// return value will need to be passed from the new thread to the thread -/// where it is `join`ed. -/// As a reminder, the [`Send`] marker trait expresses that it is safe to be -/// passed from thread to thread. [`Sync`] expresses that it is safe to have a -/// reference be passed from thread to thread. -/// -/// # Panics -/// -/// Panics if the OS fails to create a thread; use [`Builder::spawn`] -/// to recover from such errors. -/// -/// # Examples -/// -/// Creating a thread. -/// -/// ``` -/// use std::thread; -/// -/// let handler = thread::spawn(|| { -/// // thread code -/// }); -/// -/// handler.join().unwrap(); -/// ``` -/// -/// As mentioned in the module documentation, threads are usually made to -/// communicate using [`channels`], here is how it usually looks. -/// -/// This example also shows how to use `move`, in order to give ownership -/// of values to a thread. -/// -/// ``` -/// use std::thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx, rx) = channel(); -/// -/// let sender = thread::spawn(move || { -/// tx.send("Hello, thread".to_owned()) -/// .expect("Unable to send on channel"); -/// }); -/// -/// let receiver = thread::spawn(move || { -/// let value = rx.recv().expect("Unable to receive from channel"); -/// println!("{value}"); -/// }); -/// -/// sender.join().expect("The sender thread has panicked"); -/// receiver.join().expect("The receiver thread has panicked"); -/// ``` -/// -/// A thread can also return a value through its [`JoinHandle`], you can use -/// this to make asynchronous computations (futures might be more appropriate -/// though). -/// -/// ``` -/// use std::thread; -/// -/// let computation = thread::spawn(|| { -/// // Some expensive computation. -/// 42 -/// }); -/// -/// let result = computation.join().unwrap(); -/// println!("{result}"); -/// ``` -/// -/// # Notes -/// -/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g. -/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a -/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn` -/// unwinds all the way to the root with such an exception, one of two behaviors are possible, -/// and it is unspecified which will occur: -/// -/// * The process aborts. -/// * The process does not abort, and [`join`] will return a `Result::Err` -/// containing an opaque type. -/// -/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html -/// [`channels`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Err`]: crate::result::Result::Err -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn spawn(f: F) -> JoinHandle -where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -{ - Builder::new().spawn(f).expect("failed to spawn thread") -} - -/// Cooperatively gives up a timeslice to the OS scheduler. -/// -/// This calls the underlying OS scheduler's yield primitive, signaling -/// that the calling thread is willing to give up its remaining timeslice -/// so that the OS may schedule other threads on the CPU. -/// -/// A drawback of yielding in a loop is that if the OS does not have any -/// other ready threads to run on the current CPU, the thread will effectively -/// busy-wait, which wastes CPU time and energy. -/// -/// Therefore, when waiting for events of interest, a programmer's first -/// choice should be to use synchronization devices such as [`channel`]s, -/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are -/// implemented in a blocking manner, giving up the CPU until the event -/// of interest has occurred which avoids repeated yielding. -/// -/// `yield_now` should thus be used only rarely, mostly in situations where -/// repeated polling is required because there is no other suitable way to -/// learn when an event of interest has occurred. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// thread::yield_now(); -/// ``` -/// -/// [`channel`]: crate::sync::mpsc -/// [`join`]: JoinHandle::join -/// [`Condvar`]: crate::sync::Condvar -/// [`Mutex`]: crate::sync::Mutex -#[stable(feature = "rust1", since = "1.0.0")] -pub fn yield_now() { - imp::yield_now() -} - -/// Determines whether the current thread is unwinding because of panic. -/// -/// A common use of this feature is to poison shared resources when writing -/// unsafe code, by checking `panicking` when the `drop` is called. -/// -/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex] -/// already poison themselves when a thread panics while holding the lock. -/// -/// This can also be used in multithreaded applications, in order to send a -/// message to other threads warning that a thread has panicked (e.g., for -/// monitoring purposes). -/// -/// # Examples -/// -/// ```should_panic -/// use std::thread; -/// -/// struct SomeStruct; -/// -/// impl Drop for SomeStruct { -/// fn drop(&mut self) { -/// if thread::panicking() { -/// println!("dropped while unwinding"); -/// } else { -/// println!("dropped while not unwinding"); -/// } -/// } -/// } -/// -/// { -/// print!("a: "); -/// let a = SomeStruct; -/// } -/// -/// { -/// print!("b: "); -/// let b = SomeStruct; -/// panic!() -/// } -/// ``` -/// -/// [Mutex]: crate::sync::Mutex -#[inline] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn panicking() -> bool { - panicking::panicking() -} - -/// Uses [`sleep`]. -/// -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// -/// // Let's sleep for 2 seconds: -/// thread::sleep_ms(2000); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")] -pub fn sleep_ms(ms: u32) { - sleep(Duration::from_millis(ms as u64)) -} - -/// Puts the current thread to sleep for at least the specified amount of time. -/// -/// The thread may sleep longer than the duration specified due to scheduling -/// specifics or platform-dependent functionality. It will never sleep less. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// On Unix platforms, the underlying syscall may be interrupted by a -/// spurious wakeup or signal handler. To ensure the sleep occurs for at least -/// the specified duration, this function may invoke that system call multiple -/// times. -/// Platforms which do not support nanosecond precision for sleeping will -/// have `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// Currently, specifying a zero duration on Unix platforms returns immediately -/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows -/// platforms the underlying [`Sleep`] syscall is always invoked. -/// If the intention is to yield the current time-slice you may want to use -/// [`yield_now`] instead. -/// -/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep -/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep -/// -/// # Examples -/// -/// ```no_run -/// use std::{thread, time}; -/// -/// let ten_millis = time::Duration::from_millis(10); -/// let now = time::Instant::now(); -/// -/// thread::sleep(ten_millis); -/// -/// assert!(now.elapsed() >= ten_millis); -/// ``` -#[stable(feature = "thread_sleep", since = "1.4.0")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - -/// Puts the current thread to sleep until the specified deadline has passed. -/// -/// The thread may still be asleep after the deadline specified due to -/// scheduling specifics or platform-dependent functionality. It will never -/// wake before. -/// -/// This function is blocking, and should not be used in `async` functions. -/// -/// # Platform-specific behavior -/// -/// In most cases this function will call an OS specific function. Where that -/// is not supported [`sleep`] is used. Those platforms are referred to as other -/// in the table below. -/// -/// # Underlying System calls -/// -/// The following system calls are [currently] being used: -/// -/// | Platform | System call | -/// |-----------|----------------------------------------------------------------------| -/// | Linux | [clock_nanosleep] (Monotonic clock) | -/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | -/// | Android | [clock_nanosleep] (Monotonic Clock)] | -/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | -/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | -/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | -/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | -/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | -/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | -/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | -/// -/// [currently]: crate::io#platform-specific-behavior -/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep -/// -/// **Disclaimer:** These system calls might change over time. -/// -/// # Examples -/// -/// A simple game loop that limits the game to 60 frames per second. -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # fn update() {} -/// # fn render() {} -/// # -/// let max_fps = 60.0; -/// let frame_time = Duration::from_secs_f32(1.0/max_fps); -/// let mut next_frame = Instant::now(); -/// loop { -/// thread::sleep_until(next_frame); -/// next_frame += frame_time; -/// update(); -/// render(); -/// } -/// ``` -/// -/// A slow API we must not call too fast and which takes a few -/// tries before succeeding. By using `sleep_until` the time the -/// API call takes does not influence when we retry or when we give up -/// -/// ```no_run -/// #![feature(thread_sleep_until)] -/// # use std::time::{Duration, Instant}; -/// # use std::thread; -/// # -/// # enum Status { -/// # Ready(usize), -/// # Waiting, -/// # } -/// # fn slow_web_api_call() -> Status { Status::Ready(42) } -/// # -/// # const MAX_DURATION: Duration = Duration::from_secs(10); -/// # -/// # fn try_api_call() -> Result { -/// let deadline = Instant::now() + MAX_DURATION; -/// let delay = Duration::from_millis(250); -/// let mut next_attempt = Instant::now(); -/// loop { -/// if Instant::now() > deadline { -/// break Err(()); -/// } -/// if let Status::Ready(data) = slow_web_api_call() { -/// break Ok(data); -/// } -/// -/// next_attempt = deadline.min(next_attempt + delay); -/// thread::sleep_until(next_attempt); -/// } -/// # } -/// # let _data = try_api_call(); -/// ``` -#[unstable(feature = "thread_sleep_until", issue = "113752")] -pub fn sleep_until(deadline: Instant) { - imp::sleep_until(deadline) -} - -/// Used to ensure that `park` and `park_timeout` do not unwind, as that can -/// cause undefined behavior if not handled correctly (see #102398 for context). -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("an irrecoverable error occurred while synchronizing threads") - } -} - -/// Blocks unless or until the current thread's token is made available. -/// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. However, -/// it is guaranteed that this function will not panic (it may abort the -/// process if the implementation encounters some rare errors). -/// -/// # `park` and `unpark` -/// -/// Every thread is equipped with some basic low-level blocking support, via the -/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] -/// method. [`park`] blocks the current thread, which can then be resumed from -/// another thread by calling the [`unpark`] method on the blocked thread's -/// handle. -/// -/// Conceptually, each [`Thread`] handle has an associated token, which is -/// initially not present: -/// -/// * The [`thread::park`][`park`] function blocks the current thread unless or -/// until the token is available for its thread handle, at which point it -/// atomically consumes the token. It may also return *spuriously*, without -/// consuming the token. [`thread::park_timeout`] does the same, but allows -/// specifying a maximum time to block the thread for. -/// -/// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. Because the token can be held by a thread even if it is currently not -/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately. -/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens -/// after all `park` that may be done by other data structures! -/// -/// The API is typically used by acquiring a handle to the current thread, placing that handle in a -/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some -/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point -/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it -/// will be woken up properly. -/// -/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread -/// without first establishing that it is about to be `park`ing within your code, that `unpark` may -/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means -/// you must not call unknown code between setting up for parking and calling `park`; for instance, -/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a -/// deadlock. -/// -/// The motivation for this design is twofold: -/// -/// * It avoids the need to allocate mutexes and condvars when building new -/// synchronization primitives; the threads already provide basic -/// blocking/signaling. -/// -/// * It can be implemented very efficiently on many platforms. -/// -/// # Memory Ordering -/// -/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory -/// operations performed before a call to `unpark` are made visible to the thread that -/// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and _all_ prior `unpark` operations -/// synchronize-with `park`. -/// -/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` -/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same -/// thread form a [release sequence]. -/// -/// Note that being unblocked does not imply a call was made to `unpark`, because -/// wakeups can also be spurious. For example, a valid, but inefficient, -/// implementation could have `park` and `unpark` return immediately without doing anything, -/// making *all* wakeups spurious. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// use std::sync::atomic::{Ordering, AtomicBool}; -/// use std::time::Duration; -/// -/// static QUEUED: AtomicBool = AtomicBool::new(false); -/// static FLAG: AtomicBool = AtomicBool::new(false); -/// -/// let parked_thread = thread::spawn(move || { -/// println!("Thread spawned"); -/// // Signal that we are going to `park`. Between this store and our `park`, there may -/// // be no other `park`, or else that `park` could consume our `unpark` token! -/// QUEUED.store(true, Ordering::Release); -/// // We want to wait until the flag is set. We *could* just spin, but using -/// // park/unpark is more efficient. -/// while !FLAG.load(Ordering::Acquire) { -/// // We can *not* use `println!` here since that could use thread parking internally. -/// thread::park(); -/// // We *could* get here spuriously, i.e., way before the 10ms below are over! -/// // But that is no problem, we are in a loop until the flag is set anyway. -/// } -/// println!("Flag received"); -/// }); -/// -/// // Let some time pass for the thread to be spawned. -/// thread::sleep(Duration::from_millis(10)); -/// -/// // Ensure the thread is about to park. -/// // This is crucial! It guarantees that the `unpark` below is not consumed -/// // by some other code in the parked thread (e.g. inside `println!`). -/// while !QUEUED.load(Ordering::Acquire) { -/// // Spinning is of course inefficient; in practice, this would more likely be -/// // a dequeue where we have no work to do if there's nobody queued. -/// std::hint::spin_loop(); -/// } -/// -/// // Set the flag, and let the thread wake up. -/// // There is no race condition here: if `unpark` -/// // happens first, `park` will return immediately. -/// // There is also no other `park` that could consume this token, -/// // since we waited until the other thread got queued. -/// // Hence there is no risk of a deadlock. -/// FLAG.store(true, Ordering::Release); -/// println!("Unpark the thread"); -/// parked_thread.thread().unpark(); -/// -/// parked_thread.join().unwrap(); -/// ``` -/// -/// [`unpark`]: Thread::unpark -/// [`thread::park_timeout`]: park_timeout -/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence -#[stable(feature = "rust1", since = "1.0.0")] -pub fn park() { - let guard = PanicGuard; - // SAFETY: park_timeout is called on the parker owned by this thread. - unsafe { - current().park(); - } - // No panic occurred, do not abort. - forget(guard); -} - -/// Uses [`park_timeout`]. -/// -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `ms` long. -/// -/// See the [park documentation][`park`] for more detail. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")] -pub fn park_timeout_ms(ms: u32) { - park_timeout(Duration::from_millis(ms as u64)) -} - -/// Blocks unless or until the current thread's token is made available or -/// the specified duration has been reached (may wake spuriously). -/// -/// The semantics of this function are equivalent to [`park`][park] except -/// that the thread will be blocked for roughly no longer than `dur`. This -/// method should not be used for precise timing due to anomalies such as -/// preemption or platform differences that might not cause the maximum -/// amount of time waited to be precisely `dur` long. -/// -/// See the [park documentation][park] for more details. -/// -/// # Platform-specific behavior -/// -/// Platforms which do not support nanosecond precision for sleeping will have -/// `dur` rounded up to the nearest granularity of time they can sleep for. -/// -/// # Examples -/// -/// Waiting for the complete expiration of the timeout: -/// -/// ```rust,no_run -/// use std::thread::park_timeout; -/// use std::time::{Instant, Duration}; -/// -/// let timeout = Duration::from_secs(2); -/// let beginning_park = Instant::now(); -/// -/// let mut timeout_remaining = timeout; -/// loop { -/// park_timeout(timeout_remaining); -/// let elapsed = beginning_park.elapsed(); -/// if elapsed >= timeout { -/// break; -/// } -/// println!("restarting park_timeout after {elapsed:?}"); -/// timeout_remaining = timeout - elapsed; -/// } -/// ``` -#[stable(feature = "park_timeout", since = "1.4.0")] -pub fn park_timeout(dur: Duration) { - let guard = PanicGuard; - // SAFETY: park_timeout is called on a handle owned by this thread. - unsafe { - current().park_timeout(dur); - } - // No panic occurred, do not abort. - forget(guard); -} - -//////////////////////////////////////////////////////////////////////////////// -// ThreadId -//////////////////////////////////////////////////////////////////////////////// - -/// A unique identifier for a running thread. -/// -/// A `ThreadId` is an opaque object that uniquely identifies each thread -/// created during the lifetime of a process. `ThreadId`s are guaranteed not to -/// be reused, even when a thread terminates. `ThreadId`s are under the control -/// of Rust's standard library and there may not be any relationship between -/// `ThreadId` and the underlying platform's notion of a thread identifier -- -/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` -/// can be retrieved from the [`id`] method on a [`Thread`]. -/// -/// # Examples -/// -/// ``` -/// use std::thread; -/// -/// let other_thread = thread::spawn(|| { -/// thread::current().id() -/// }); -/// -/// let other_thread_id = other_thread.join().unwrap(); -/// assert!(thread::current().id() != other_thread_id); -/// ``` -/// -/// [`id`]: Thread::id -#[stable(feature = "thread_id", since = "1.19.0")] -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct ThreadId(NonZero); - -impl ThreadId { - // Generate a new unique thread ID. - pub(crate) fn new() -> ThreadId { - #[cold] - fn exhausted() -> ! { - panic!("failed to generate unique thread ID: bitspace exhausted") - } - - cfg_select! { - target_has_atomic = "64" => { - use crate::sync::atomic::{Atomic, AtomicU64}; - - static COUNTER: Atomic = AtomicU64::new(0); - - let mut last = COUNTER.load(Ordering::Relaxed); - loop { - let Some(id) = last.checked_add(1) else { - exhausted(); - }; - - match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => return ThreadId(NonZero::new(id).unwrap()), - Err(id) => last = id, - } - } - } - _ => { - use crate::cell::SyncUnsafeCell; - use crate::hint::spin_loop; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::thread::yield_now; - - // If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex - // here as we might be trying to get the current thread id in the global allocator, - // and on some platforms Mutex requires allocation. - static COUNTER_LOCKED: Atomic = AtomicBool::new(false); - static COUNTER: SyncUnsafeCell = SyncUnsafeCell::new(0); - - // Acquire lock. - let mut spin = 0; - while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { - if spin <= 3 { - for _ in 0..(1 << spin) { - spin_loop(); - } - } else { - yield_now(); - } - spin += 1; - } - - // SAFETY: we have an exclusive lock on the counter. - unsafe { - if let Some(id) = (*COUNTER.get()).checked_add(1) { - *COUNTER.get() = id; - COUNTER_LOCKED.store(false, Ordering::Release); - ThreadId(NonZero::new(id).unwrap()) - } else { - COUNTER_LOCKED.store(false, Ordering::Release); - exhausted() - } - } - } - } - } - - #[cfg(any(not(target_thread_local), target_has_atomic = "64"))] - fn from_u64(v: u64) -> Option { - NonZero::new(v).map(ThreadId) - } - - /// This returns a numeric identifier for the thread identified by this - /// `ThreadId`. - /// - /// As noted in the documentation for the type itself, it is essentially an - /// opaque ID, but is guaranteed to be unique for each thread. The returned - /// value is entirely opaque -- only equality testing is stable. Note that - /// it is not guaranteed which values new threads will return, and this may - /// change across Rust versions. - #[must_use] - #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZero { - self.0 - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Thread -//////////////////////////////////////////////////////////////////////////////// +use crate::time::Duration; // This module ensures private fields are kept private, which is necessary to enforce the safety requirements. mod thread_name_string { @@ -1376,100 +40,6 @@ mod thread_name_string { use thread_name_string::ThreadNameString; -/// Store the ID of the main thread. -/// -/// The thread handle for the main thread is created lazily, and this might even -/// happen pre-main. Since not every platform has a way to identify the main -/// thread when that happens – macOS's `pthread_main_np` function being a notable -/// exception – we cannot assign it the right name right then. Instead, in our -/// runtime startup code, we remember the thread ID of the main thread (through -/// this modules `set` function) and use it to identify the main thread from then -/// on. This works reliably and has the additional advantage that we can report -/// the right thread name on main even after the thread handle has been destroyed. -/// Note however that this also means that the name reported in pre-main functions -/// will be incorrect, but that's just something we have to live with. -pub(crate) mod main_thread { - cfg_select! { - target_has_atomic = "64" => { - use super::ThreadId; - use crate::sync::atomic::{Atomic, AtomicU64}; - use crate::sync::atomic::Ordering::Relaxed; - - static MAIN: Atomic = AtomicU64::new(0); - - pub(super) fn get() -> Option { - ThreadId::from_u64(MAIN.load(Relaxed)) - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - MAIN.store(id.as_u64().get(), Relaxed) - } - } - _ => { - use super::ThreadId; - use crate::mem::MaybeUninit; - use crate::sync::atomic::{Atomic, AtomicBool}; - use crate::sync::atomic::Ordering::{Acquire, Release}; - - static INIT: Atomic = AtomicBool::new(false); - static mut MAIN: MaybeUninit = MaybeUninit::uninit(); - - pub(super) fn get() -> Option { - if INIT.load(Acquire) { - Some(unsafe { MAIN.assume_init() }) - } else { - None - } - } - - /// # Safety - /// May only be called once. - pub(crate) unsafe fn set(id: ThreadId) { - unsafe { MAIN = MaybeUninit::new(id) }; - INIT.store(true, Release); - } - } - } -} - -/// Run a function with the current thread's name. -/// -/// Modulo thread local accesses, this function is safe to call from signal -/// handlers and in similar circumstances where allocations are not possible. -pub(crate) fn with_current_name(f: F) -> R -where - F: FnOnce(Option<&str>) -> R, -{ - try_with_current(|thread| { - if let Some(thread) = thread { - // If there is a current thread handle, try to use the name stored - // there. - if let Some(name) = &thread.inner.name { - return f(Some(name.as_str())); - } else if Some(thread.inner.id) == main_thread::get() { - // The main thread doesn't store its name in the handle, we must - // identify it through its ID. Since we already have the `Thread`, - // we can retrieve the ID from it instead of going through another - // thread local. - return f(Some("main")); - } - } else if let Some(main) = main_thread::get() - && let Some(id) = current::id::get() - && id == main - { - // The main thread doesn't always have a thread handle, we must - // identify it through its ID instead. The checks are ordered so - // that the current ID is only loaded if it is actually needed, - // since loading it from TLS might need multiple expensive accesses. - return f(Some("main")); - } - - f(None) - }) -} - /// The internal representation of a `Thread` handle /// /// We explicitly set the alignment for our guarantee in Thread::into_raw. This @@ -1743,404 +313,3 @@ impl fmt::Debug for Thread { .finish_non_exhaustive() } } - -//////////////////////////////////////////////////////////////////////////////// -// JoinHandle -//////////////////////////////////////////////////////////////////////////////// - -/// A specialized [`Result`] type for threads. -/// -/// Indicates the manner in which a thread exited. -/// -/// The value contained in the `Result::Err` variant -/// is the value the thread panicked with; -/// that is, the argument the `panic!` macro was called with. -/// Unlike with normal errors, this value doesn't implement -/// the [`Error`](crate::error::Error) trait. -/// -/// Thus, a sensible way to handle a thread panic is to either: -/// -/// 1. propagate the panic with [`std::panic::resume_unwind`] -/// 2. or in case the thread is intended to be a subsystem boundary -/// that is supposed to isolate system-level failures, -/// match on the `Err` variant and handle the panic in an appropriate way -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// # Examples -/// -/// Matching on the result of a joined thread: -/// -/// ```no_run -/// use std::{fs, thread, panic}; -/// -/// fn copy_in_thread() -> thread::Result<()> { -/// thread::spawn(|| { -/// fs::copy("foo.txt", "bar.txt").unwrap(); -/// }).join() -/// } -/// -/// fn main() { -/// match copy_in_thread() { -/// Ok(_) => println!("copy succeeded"), -/// Err(e) => panic::resume_unwind(e), -/// } -/// } -/// ``` -/// -/// [`Result`]: crate::result::Result -/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(search_unbox)] -pub type Result = crate::result::Result>; - -// This packet is used to communicate the return value between the spawned -// thread and the rest of the program. It is shared through an `Arc` and -// there's no need for a mutex here because synchronization happens with `join()` -// (the caller will never read this packet until the thread has exited). -// -// An Arc to the packet is stored into a `JoinInner` which in turns is placed -// in `JoinHandle`. -struct Packet<'scope, T> { - scope: Option>, - result: UnsafeCell>>, - _marker: PhantomData>, -} - -// Due to the usage of `UnsafeCell` we need to manually implement Sync. -// The type `T` should already always be Send (otherwise the thread could not -// have been created) and the Packet is Sync because all access to the -// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} - -impl<'scope, T> Drop for Packet<'scope, T> { - fn drop(&mut self) { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result without causing unwinding. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this panics, we should handle that, because we're outside the - // outermost `catch_unwind` of our thread. - // We just abort in that case, since there's nothing else we can do. - // (And even if we tried to handle it somehow, we'd also need to handle - // the case where the panic payload we get out of it also panics on - // drop, and so on. See issue #86027.) - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { - *self.result.get_mut() = None; - })) { - rtabort!("thread result panicked on drop"); - } - // Book-keeping so the scope knows when it's done. - if let Some(scope) = &self.scope { - // Now that there will be no more user code running on this thread - // that can use 'scope, mark the thread as 'finished'. - // It's important we only do this after the `result` has been dropped, - // since dropping it might still use things it borrowed from 'scope. - scope.decrement_num_running_threads(unhandled_panic); - } - } -} - -/// Inner representation for JoinHandle -struct JoinInner<'scope, T> { - native: imp::Thread, - thread: Thread, - packet: Arc>, -} - -impl<'scope, T> JoinInner<'scope, T> { - fn join(mut self) -> Result { - self.native.join(); - Arc::get_mut(&mut self.packet) - // FIXME(fuzzypixelz): returning an error instead of panicking here - // would require updating the documentation of - // `std::thread::Result`; currently we can return `Err` if and only - // if the thread had panicked. - .expect("threads should not terminate unexpectedly") - .result - .get_mut() - .take() - .unwrap() - } -} - -/// An owned permission to join on a thread (block on its termination). -/// -/// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to the thread and no way to `join` -/// on it. -/// -/// Due to platform restrictions, it is not possible to [`Clone`] this -/// handle: the ability to join a thread is a uniquely-owned permission. -/// -/// This `struct` is created by the [`thread::spawn`] function and the -/// [`thread::Builder::spawn`] method. -/// -/// # Examples -/// -/// Creation from [`thread::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| { -/// // some work here -/// }); -/// ``` -/// -/// Creation from [`thread::Builder::spawn`]: -/// -/// ``` -/// use std::thread; -/// -/// let builder = thread::Builder::new(); -/// -/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { -/// // some work here -/// }).unwrap(); -/// ``` -/// -/// A thread being detached and outliving the thread that spawned it: -/// -/// ```no_run -/// use std::thread; -/// use std::time::Duration; -/// -/// let original_thread = thread::spawn(|| { -/// let _detached_thread = thread::spawn(|| { -/// // Here we sleep to make sure that the first thread returns before. -/// thread::sleep(Duration::from_millis(10)); -/// // This will be called, even though the JoinHandle is dropped. -/// println!("♫ Still alive ♫"); -/// }); -/// }); -/// -/// original_thread.join().expect("The thread being joined has panicked"); -/// println!("Original thread is joined."); -/// -/// // We make sure that the new thread has time to run, before the main -/// // thread returns. -/// -/// thread::sleep(Duration::from_millis(1000)); -/// ``` -/// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(target_os = "teeos", must_use)] -pub struct JoinHandle(JoinInner<'static, T>); - -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Send for JoinHandle {} -#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] -unsafe impl Sync for JoinHandle {} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// - /// let thread = join_handle.thread(); - /// println!("thread id: {:?}", thread.id()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn thread(&self) -> &Thread { - &self.0.thread - } - - /// Waits for the associated thread to finish. - /// - /// This function will return immediately if the associated thread has already finished. - /// - /// In terms of [atomic memory orderings], the completion of the associated - /// thread synchronizes with this function returning. In other words, all - /// operations performed by that thread [happen - /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all - /// operations that happen after `join` returns. - /// - /// If the associated thread panics, [`Err`] is returned with the parameter given - /// to [`panic!`] (though see the Notes below). - /// - /// [`Err`]: crate::result::Result::Err - /// [atomic memory orderings]: crate::sync::atomic - /// - /// # Panics - /// - /// This function may panic on some platforms if a thread attempts to join - /// itself or otherwise may create a deadlock with joining threads. - /// - /// # Examples - /// - /// ``` - /// use std::thread; - /// - /// let builder = thread::Builder::new(); - /// - /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| { - /// // some work here - /// }).unwrap(); - /// join_handle.join().expect("Couldn't join on the associated thread"); - /// ``` - /// - /// # Notes - /// - /// If a "foreign" unwinding operation (e.g. an exception thrown from C++ - /// code, or a `panic!` in Rust code compiled or linked with a different - /// runtime) unwinds all the way to the thread root, the process may be - /// aborted; see the Notes on [`thread::spawn`]. If the process is not - /// aborted, this function will return a `Result::Err` containing an opaque - /// type. - /// - /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn - #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(self) -> Result { - self.0.join() - } - - /// Checks if the associated thread has finished running its main function. - /// - /// `is_finished` supports implementing a non-blocking join operation, by checking - /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To - /// block while waiting on the thread to finish, use [`join`][Self::join]. - /// - /// This might return `true` for a brief moment after the thread's main - /// function has returned, but before the thread itself has stopped running. - /// However, once this returns `true`, [`join`][Self::join] can be expected - /// to return quickly, without blocking for any significant amount of time. - #[stable(feature = "thread_is_running", since = "1.61.0")] - pub fn is_finished(&self) -> bool { - Arc::strong_count(&self.0.packet) == 1 - } -} - -impl AsInner for JoinHandle { - fn as_inner(&self) -> &imp::Thread { - &self.0.native - } -} - -impl IntoInner for JoinHandle { - fn into_inner(self) -> imp::Thread { - self.0.native - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for JoinHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("JoinHandle").finish_non_exhaustive() - } -} - -fn _assert_sync_and_send() { - fn _assert_both() {} - _assert_both::>(); - _assert_both::(); -} - -/// Returns an estimate of the default amount of parallelism a program should use. -/// -/// Parallelism is a resource. A given machine provides a certain capacity for -/// parallelism, i.e., a bound on the number of computations it can perform -/// simultaneously. This number often corresponds to the amount of CPUs a -/// computer has, but it may diverge in various cases. -/// -/// Host environments such as VMs or container orchestrators may want to -/// restrict the amount of parallelism made available to programs in them. This -/// is often done to limit the potential impact of (unintentionally) -/// resource-intensive programs on other programs running on the same machine. -/// -/// # Limitations -/// -/// The purpose of this API is to provide an easy and portable way to query -/// the default amount of parallelism the program should use. Among other things it -/// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities or current system load, -/// and will not modify the program's global state in order to more accurately -/// query the amount of available parallelism. -/// -/// Where both fixed steady-state and burst limits are available the steady-state -/// capacity will be used to ensure more predictable latencies. -/// -/// Resource limits can be changed during the runtime of a program, therefore the value is -/// not cached and instead recomputed every time this function is called. It should not be -/// called from hot code. -/// -/// The value returned by this function should be considered a simplified -/// approximation of the actual amount of parallelism available at any given -/// time. To get a more detailed or precise overview of the amount of -/// parallelism available to the program, you may wish to use -/// platform-specific APIs as well. The following platform limitations currently -/// apply to `available_parallelism`: -/// -/// On Windows: -/// - It may undercount the amount of parallelism available on systems with more -/// than 64 logical CPUs. However, programs typically need specific support to -/// take advantage of more than 64 logical CPUs, and in the absence of such -/// support, the number returned by this function accurately reflects the -/// number of logical CPUs the program can use by default. -/// - It may overcount the amount of parallelism available on systems limited by -/// process-wide affinity masks, or job object limitations. -/// -/// On Linux: -/// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be -/// queried, e.g. due to sandboxing. -/// - It may undercount the amount of parallelism if the current thread's affinity mask -/// does not reflect the process' cpuset, e.g. due to pinned threads. -/// - If the process is in a cgroup v1 cpu controller, this may need to -/// scan mountpoints to find the corresponding cgroup v1 controller, -/// which may take time on systems with large numbers of mountpoints. -/// (This does not apply to cgroup v2, or to processes not in a -/// cgroup.) -/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of -/// threads, `available_parallelism` cannot know how much of that limit a Rust program should -/// take, or know in a reliable and race-free way how much of that limit is already taken. -/// -/// On all targets: -/// - It may overcount the amount of parallelism available when running in a VM -/// with CPU usage limits (e.g. an overcommitted host). -/// -/// # Errors -/// -/// This function will, but is not limited to, return errors in the following -/// cases: -/// -/// - If the amount of parallelism is not known for the target platform. -/// - If the program lacks permission to query the amount of parallelism made -/// available to it. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::{io, thread}; -/// -/// fn main() -> io::Result<()> { -/// let count = thread::available_parallelism()?.get(); -/// assert!(count >= 1_usize); -/// Ok(()) -/// } -/// ``` -#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. -#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. -#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result> { - imp::available_parallelism() -} From 912f7f9502b7d7917228e153ba8f678831a63f1a Mon Sep 17 00:00:00 2001 From: joboet Date: Sun, 9 Nov 2025 22:19:32 +0100 Subject: [PATCH 3/5] update references to thread implementation in tests --- .../fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr | 4 ++-- .../libc_pthread_rwlock_write_read_deadlock.stderr | 4 ++-- .../libc_pthread_rwlock_write_write_deadlock.stderr | 4 ++-- .../tests/fail-dep/concurrency/windows_join_detached.stderr | 4 ++-- .../miri/tests/fail-dep/concurrency/windows_join_main.stderr | 4 ++-- .../miri/tests/fail-dep/concurrency/windows_join_self.stderr | 4 ++-- .../miri/tests/fail-dep/libc/eventfd_block_read_twice.stderr | 4 ++-- .../miri/tests/fail-dep/libc/eventfd_block_write_twice.stderr | 4 ++-- .../tests/fail-dep/libc/libc_epoll_block_two_thread.stderr | 4 ++-- .../tests/fail-dep/libc/socketpair-close-while-blocked.stderr | 4 ++-- .../tests/fail-dep/libc/socketpair_block_read_twice.stderr | 4 ++-- .../tests/fail-dep/libc/socketpair_block_write_twice.stderr | 4 ++-- tests/ui/binop/binary-op-not-allowed-issue-125631.stderr | 4 ++-- tests/ui/closures/closure-move-sync.stderr | 2 +- tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr | 2 +- .../ui/errors/remap-path-prefix-sysroot.without-remap.stderr | 2 +- tests/ui/threads-sendsync/rc-is-not-send.stderr | 2 +- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr index 582c6f11e3602..c80cbf835a386 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr @@ -12,8 +12,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_read_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_read_deadlock.stderr index d8d0ff37e4100..f174d387f76e3 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_read_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_read_deadlock.stderr @@ -12,8 +12,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/concurrency/libc_pthread_rwlock_write_read_deadlock.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_write_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_write_deadlock.stderr index c9a4004ebfb31..06b8e1246e016 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_write_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_write_write_deadlock.stderr @@ -12,8 +12,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/concurrency/libc_pthread_rwlock_write_write_deadlock.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr index 47a0ebdcfef82..52affb767db51 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr @@ -8,8 +8,8 @@ LL | let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle( = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/concurrency/windows_join_detached.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr index 93f800ecca331..0ab89676db370 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr @@ -14,8 +14,8 @@ LL | let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle( | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/concurrency/windows_join_main.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr index c76da9151b35e..bdfab966d6d98 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr @@ -12,8 +12,8 @@ LL | let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle( | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/concurrency/windows_join_self.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.stderr b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.stderr index a7dfa0b6ea650..6253fe6d2c768 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.stderr +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.stderr @@ -6,8 +6,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/libc/eventfd_block_read_twice.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.stderr b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.stderr index 0e554598ecf56..aecc54c2fd882 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.stderr +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.stderr @@ -6,8 +6,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/libc/eventfd_block_write_twice.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr index 6740faedb3e9d..14390d632738d 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr +++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr @@ -6,8 +6,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair-close-while-blocked.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair-close-while-blocked.stderr index 1e802209fd795..97b5df7fb17ff 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair-close-while-blocked.stderr +++ b/src/tools/miri/tests/fail-dep/libc/socketpair-close-while-blocked.stderr @@ -6,8 +6,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/libc/socketpair-close-while-blocked.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.stderr index 3f7bbc779609f..38db735e9b4d4 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.stderr +++ b/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.stderr @@ -6,8 +6,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/libc/socketpair_block_read_twice.rs:LL:CC | diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.stderr index b8dbb513da209..a2f1c67b5efc8 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.stderr +++ b/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.stderr @@ -6,8 +6,8 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; | = note: BACKTRACE: = note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC - = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC - = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC + = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC note: inside `main` --> tests/fail-dep/libc/socketpair_block_write_twice.rs:LL:CC | diff --git a/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr b/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr index d95876659c7ac..a997fbee1f2a0 100644 --- a/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr +++ b/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr @@ -30,7 +30,7 @@ LL | == (Error::new(ErrorKind::Other, "2"), thread::current()); | ^^ ------------------------------------------------------ (std::io::Error, Thread) | note: `Thread` does not implement `PartialEq` - --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + --> $SRC_DIR/std/src/thread/thread.rs:LL:COL | = note: `Thread` is defined in another crate note: `std::io::Error` does not implement `PartialEq` @@ -54,7 +54,7 @@ LL | struct T1; LL | struct T2; | ^^^^^^^^^ must implement `PartialEq` note: `Thread` does not implement `PartialEq` - --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + --> $SRC_DIR/std/src/thread/thread.rs:LL:COL | = note: `Thread` is defined in another crate note: `std::io::Error` does not implement `PartialEq` diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr index 2bb26b0c0b7d4..7241f78c3539e 100644 --- a/tests/ui/closures/closure-move-sync.stderr +++ b/tests/ui/closures/closure-move-sync.stderr @@ -18,7 +18,7 @@ note: required because it's used within this closure LL | let t = thread::spawn(|| { | ^^ note: required by a bound in `spawn` - --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + --> $SRC_DIR/std/src/thread/functions.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr b/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr index 88d713d2b048c..8540f492a662a 100644 --- a/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr +++ b/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr @@ -7,7 +7,7 @@ LL | self.thread.join().unwrap(); | move occurs because `self.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: `JoinHandle::::join` takes ownership of the receiver `self`, which moves `self.thread` - --> remapped/library/std/src/thread/mod.rs:LL:COL + --> remapped/library/std/src/thread/join_handle.rs:LL:COL | LL | pub fn join(self) -> Result { | ^^^^ diff --git a/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr b/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr index 9b337699c3295..91a3d5b5d6c8a 100644 --- a/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr +++ b/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr @@ -7,7 +7,7 @@ LL | self.thread.join().unwrap(); | move occurs because `self.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: `JoinHandle::::join` takes ownership of the receiver `self`, which moves `self.thread` - --> $SRC_DIR_REAL/std/src/thread/mod.rs:LL:COL + --> $SRC_DIR_REAL/std/src/thread/join_handle.rs:LL:COL | LL | pub fn join(self) -> Result { | ^^^^ diff --git a/tests/ui/threads-sendsync/rc-is-not-send.stderr b/tests/ui/threads-sendsync/rc-is-not-send.stderr index a06b683f729e0..784a0999c6011 100644 --- a/tests/ui/threads-sendsync/rc-is-not-send.stderr +++ b/tests/ui/threads-sendsync/rc-is-not-send.stderr @@ -30,7 +30,7 @@ note: required because it's used within this closure LL | thread::spawn(move || { | ^^^^^^^ note: required by a bound in `spawn` - --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + --> $SRC_DIR/std/src/thread/functions.rs:LL:COL error: aborting due to 1 previous error From 9c6e0f6f57623c7cb88b1d2bc9cef9c6f898c709 Mon Sep 17 00:00:00 2001 From: joboet Date: Sun, 9 Nov 2025 23:29:15 +0100 Subject: [PATCH 4/5] std: update broken links in `thread` module --- library/std/src/thread/builder.rs | 17 ++++++++++++----- library/std/src/thread/functions.rs | 3 ++- library/std/src/thread/id.rs | 3 ++- library/std/src/thread/join_handle.rs | 6 +++--- library/std/src/thread/mod.rs | 1 + library/std/src/thread/thread.rs | 25 ++++++++++++++++++------- 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/library/std/src/thread/builder.rs b/library/std/src/thread/builder.rs index 6b07a7fd57d3f..f4abe074ab9d7 100644 --- a/library/std/src/thread/builder.rs +++ b/library/std/src/thread/builder.rs @@ -39,7 +39,7 @@ use crate::io; /// [`stack_size`]: Builder::stack_size /// [`name`]: Builder::name /// [`spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn +/// [`thread::spawn`]: super::spawn /// [`io::Result`]: crate::io::Result /// [`unwrap`]: crate::result::Result::unwrap /// [naming-threads]: ./index.html#naming-threads @@ -133,10 +133,12 @@ impl Builder { self } - /// Disables running and inheriting [spawn hooks](add_spawn_hook). + /// Disables running and inheriting [spawn hooks]. /// /// Use this if the parent thread is in no way relevant for the child thread. /// For example, when lazily spawning threads for a thread pool. + /// + /// [spawn hooks]: super::add_spawn_hook #[unstable(feature = "thread_spawn_hook", issue = "132951")] pub fn no_hooks(mut self) -> Builder { self.no_hooks = true; @@ -151,7 +153,7 @@ impl Builder { /// thread finishes). The join handle can be used to block on /// termination of the spawned thread, including recovering its panics. /// - /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// For a more complete documentation see [`thread::spawn`]. /// /// # Errors /// @@ -178,6 +180,9 @@ impl Builder { /// /// handler.join().unwrap(); /// ``` + /// + /// [`thread::spawn`]: super::spawn + /// [`spawn`]: super::spawn #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn spawn(self, f: F) -> io::Result> @@ -199,7 +204,7 @@ impl Builder { /// /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], /// except for the relaxed lifetime bounds, which render it unsafe. - /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// For a more complete documentation see [`thread::spawn`]. /// /// # Errors /// @@ -221,7 +226,7 @@ impl Builder { /// data is dropped /// - use only types with `'static` lifetime bounds, i.e., those with no or only /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] - /// and [`thread::spawn`][`spawn`] enforce this property statically) + /// and [`thread::spawn`] enforce this property statically) /// /// # Examples /// @@ -246,6 +251,8 @@ impl Builder { /// ``` /// /// [`io::Result`]: crate::io::Result + /// [`thread::spawn`]: super::spawn + /// [`spawn`]: super::spawn #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> diff --git a/library/std/src/thread/functions.rs b/library/std/src/thread/functions.rs index b8f5049de3b1c..a25bae1aae31e 100644 --- a/library/std/src/thread/functions.rs +++ b/library/std/src/thread/functions.rs @@ -517,7 +517,8 @@ impl Drop for PanicGuard { /// parked_thread.join().unwrap(); /// ``` /// -/// [`unpark`]: Thread::unpark +/// [`Thread`]: super::Thread +/// [`unpark`]: super::Thread::unpark /// [`thread::park_timeout`]: park_timeout /// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/thread/id.rs b/library/std/src/thread/id.rs index 0e528ba25fcb7..ba7024327881b 100644 --- a/library/std/src/thread/id.rs +++ b/library/std/src/thread/id.rs @@ -24,7 +24,8 @@ use crate::sync::atomic::{Atomic, Ordering}; /// assert!(thread::current().id() != other_thread_id); /// ``` /// -/// [`id`]: Thread::id +/// [`Thread`]: super::Thread +/// [`id`]: super::Thread::id #[stable(feature = "thread_id", since = "1.19.0")] #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] pub struct ThreadId(NonZero); diff --git a/library/std/src/thread/join_handle.rs b/library/std/src/thread/join_handle.rs index 04d4733aa6bdf..8714ceeb4f467 100644 --- a/library/std/src/thread/join_handle.rs +++ b/library/std/src/thread/join_handle.rs @@ -65,8 +65,8 @@ use crate::sys_common::{AsInner, IntoInner}; /// thread::sleep(Duration::from_millis(1000)); /// ``` /// -/// [`thread::Builder::spawn`]: Builder::spawn -/// [`thread::spawn`]: spawn +/// [`thread::Builder::spawn`]: super::Builder::spawn +/// [`thread::spawn`]: super::spawn #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(target_os = "teeos", must_use)] pub struct JoinHandle(pub(super) JoinInner<'static, T>); @@ -143,7 +143,7 @@ impl JoinHandle { /// type. /// /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html - /// [`thread::spawn`]: spawn + /// [`thread::spawn`]: super::spawn #[stable(feature = "rust1", since = "1.0.0")] pub fn join(self) -> Result { self.0.join() diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 251a2feec0077..00aeb70e6e076 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -137,6 +137,7 @@ //! Note that the stack size of the main thread is *not* determined by Rust. //! //! [channels]: crate::sync::mpsc +//! [`Arc`]: crate::sync::Arc //! [`join`]: JoinHandle::join //! [`Result`]: crate::result::Result //! [`Ok`]: crate::result::Result::Ok diff --git a/library/std/src/thread/thread.rs b/library/std/src/thread/thread.rs index 7edadc041c906..7c9c91c3b0c78 100644 --- a/library/std/src/thread/thread.rs +++ b/library/std/src/thread/thread.rs @@ -65,9 +65,8 @@ impl Inner { /// Threads are represented via the `Thread` type, which you can get in one of /// two ways: /// -/// * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] -/// function, and calling [`thread`][`JoinHandle::thread`] on the -/// [`JoinHandle`]. +/// * By spawning a new thread, e.g., using the [`thread::spawn`] +/// function, and calling [`thread`] on the [`JoinHandle`]. /// * By requesting the current thread, using the [`thread::current`] function. /// /// The [`thread::current`] function is available even for threads not spawned @@ -77,7 +76,12 @@ impl Inner { /// should instead use a function like `spawn` to create new threads, see the /// docs of [`Builder`] and [`spawn`] for more details. /// -/// [`thread::current`]: current::current +/// [`thread::spawn`]: super::spawn +/// [`thread`]: super::JoinHandle::thread +/// [`JoinHandle`]: super::JoinHandle +/// [`thread::current`]: super::current::current +/// [`Builder`]: super::Builder +/// [`spawn`]: super::spawn pub struct Thread { // We use the System allocator such that creating or dropping this handle // does not interfere with a potential Global allocator using thread-local @@ -111,6 +115,8 @@ impl Thread { /// /// # Safety /// May only be called from the thread to which this handle belongs. + /// + /// [`park`]: super::park pub(crate) unsafe fn park(&self) { unsafe { self.inner.as_ref().parker().park() } } @@ -120,6 +126,8 @@ impl Thread { /// /// # Safety /// May only be called from the thread to which this handle belongs. + /// + /// [`park_timeout`]: super::park_timeout pub(crate) unsafe fn park_timeout(&self, dur: Duration) { unsafe { self.inner.as_ref().parker().park_timeout(dur) } } @@ -127,10 +135,10 @@ impl Thread { /// Atomically makes the handle's token available if it is not already. /// /// Every thread is equipped with some basic low-level blocking support, via - /// the [`park`][park] function and the `unpark()` method. These can be - /// used as a more CPU-efficient implementation of a spinlock. + /// the [`park`] function and the `unpark()` method. These can be used as a + /// more CPU-efficient implementation of a spinlock. /// - /// See the [park documentation][park] for more details. + /// See the [park documentation] for more details. /// /// # Examples /// @@ -167,6 +175,9 @@ impl Thread { /// /// parked_thread.join().unwrap(); /// ``` + /// + /// [`park`]: super::park + /// [park documentation]: super::park #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn unpark(&self) { From c22b819952f386af03b2e5b40f6ea2e0c8afaf99 Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 28 Nov 2025 14:41:54 +0100 Subject: [PATCH 5/5] update type names in debuginfo tests --- tests/debuginfo/thread.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/debuginfo/thread.rs b/tests/debuginfo/thread.rs index 4274e449f1c9d..d78dad406ac6e 100644 --- a/tests/debuginfo/thread.rs +++ b/tests/debuginfo/thread.rs @@ -9,12 +9,12 @@ //@ cdb-command:g // //@ cdb-command:dx join_handle,d -//@ cdb-check:join_handle,d [Type: std::thread::JoinHandle >] -//@ cdb-check: [...] __0 [Type: std::thread::JoinInner >] +//@ cdb-check:join_handle,d [Type: std::thread::join_handle::JoinHandle >] +//@ cdb-check: [...] __0 [Type: std::thread::lifecycle::JoinInner >] // //@ cdb-command:dx t,d -//@ cdb-check:t,d : [...] [Type: std::thread::Thread *] -//@ cdb-check:[...] inner [...][Type: core::pin::Pin >] +//@ cdb-check:t,d : [...] [Type: std::thread::thread::Thread *] +//@ cdb-check:[...] inner [...][Type: core::pin::Pin >] use std::thread;