From cecadc32d9ad8d92d7b77c226b5efc47e07b85ac Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sun, 27 Nov 2022 21:00:45 -0700 Subject: [PATCH 1/2] Initial sketch of thread scheduling API --- library/std/src/os/horizon/mod.rs | 1 + library/std/src/os/horizon/thread.rs | 47 ++++++++++++++++++++++ library/std/src/os/linux/mod.rs | 1 + library/std/src/os/linux/thread.rs | 41 +++++++++++++++++++ library/std/src/sys/hermit/thread.rs | 10 ++++- library/std/src/sys/itron/thread.rs | 10 ++++- library/std/src/sys/sgx/thread.rs | 10 ++++- library/std/src/sys/unix/thread.rs | 46 ++++++++++++++++++++- library/std/src/sys/unsupported/thread.rs | 10 ++++- library/std/src/sys/wasi/thread.rs | 10 ++++- library/std/src/sys/wasm/atomics/thread.rs | 10 ++++- library/std/src/sys/windows/thread.rs | 13 +++++- library/std/src/thread/mod.rs | 36 ++++++++++++++--- library/std/src/thread/schedule.rs | 31 ++++++++++++++ 14 files changed, 262 insertions(+), 14 deletions(-) create mode 100644 library/std/src/os/horizon/thread.rs create mode 100644 library/std/src/os/linux/thread.rs create mode 100644 library/std/src/thread/schedule.rs diff --git a/library/std/src/os/horizon/mod.rs b/library/std/src/os/horizon/mod.rs index 326d0ae9cb96d..c2182facb0658 100644 --- a/library/std/src/os/horizon/mod.rs +++ b/library/std/src/os/horizon/mod.rs @@ -4,3 +4,4 @@ pub mod fs; pub(crate) mod raw; +pub mod thread; diff --git a/library/std/src/os/horizon/thread.rs b/library/std/src/os/horizon/thread.rs new file mode 100644 index 0000000000000..c3e6c92823e0f --- /dev/null +++ b/library/std/src/os/horizon/thread.rs @@ -0,0 +1,47 @@ +#![unstable(feature = "thread_scheduling", issue = "none")] + +use crate::fmt; + +pub struct Priority(pub(crate) libc::c_int); + +impl TryFrom for Priority { + type Error = (); + + fn try_from(value: i32) -> Result { + match value { + 0x18..=0x3F => Ok(Self(value)), + _ => Err(()), + } + } +} + +impl crate::fmt::Debug for Priority { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Priority").finish_non_exhaustive() + } +} + +pub struct Affinity(pub(crate) libc::c_int); + +impl Default for Affinity { + fn default() -> Self { + Self(-2) + } +} + +impl TryFrom for Affinity { + type Error = (); + + fn try_from(value: i32) -> Result { + match value { + -2..=4 => Ok(Self(value)), + _ => Err(()), + } + } +} + +impl crate::fmt::Debug for Affinity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Affinity").finish_non_exhaustive() + } +} diff --git a/library/std/src/os/linux/mod.rs b/library/std/src/os/linux/mod.rs index c17053011adfc..631b967c5a7b0 100644 --- a/library/std/src/os/linux/mod.rs +++ b/library/std/src/os/linux/mod.rs @@ -7,3 +7,4 @@ pub mod fs; pub mod net; pub mod process; pub mod raw; +pub mod thread; diff --git a/library/std/src/os/linux/thread.rs b/library/std/src/os/linux/thread.rs new file mode 100644 index 0000000000000..6606fcf8d445b --- /dev/null +++ b/library/std/src/os/linux/thread.rs @@ -0,0 +1,41 @@ +#![unstable(feature = "thread_scheduling", issue = "none")] + +use crate::fmt; + +pub struct Priority(pub(crate) libc::c_int); + +impl Priority { + fn new(priority: i32) -> Self { + Self(priority) + } +} + +impl crate::fmt::Debug for Priority { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Priority").finish_non_exhaustive() + } +} + +pub struct Affinity(pub(crate) libc::cpu_set_t); + +impl Affinity { + pub fn new() -> Self { + unsafe { + let mut set = crate::mem::zeroed(); + libc::CPU_ZERO(&mut set); + Self(set) + } + } + + pub fn set(&mut self, cpu: usize) { + unsafe { + libc::CPU_SET(cpu, &mut self.0); + } + } +} + +impl crate::fmt::Debug for Affinity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Affinity").finish_non_exhaustive() + } +} diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index e53a1fea6a0dc..4d00de4f44b6e 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -7,6 +7,7 @@ use crate::mem; use crate::num::NonZeroUsize; use crate::sys::hermit::abi; use crate::sys::hermit::thread_local_dtor::run_dtors; +use crate::thread::NativeOptions; use crate::time::Duration; pub type Tid = abi::Tid; @@ -55,7 +56,11 @@ impl Thread { } } - pub unsafe fn new(stack: usize, p: Box) -> io::Result { + pub unsafe fn new( + stack: usize, + p: Box, + _native_options: NativeOptions, + ) -> io::Result { Thread::new_with_coreid(stack, p, -1 /* = no specific core */) } @@ -97,6 +102,9 @@ impl Thread { } } +pub type Priority = (); +pub type Affinity = (); + pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index d28f57f33be20..92735d758e2e7 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -13,6 +13,7 @@ use crate::{ mem::ManuallyDrop, sync::atomic::{AtomicUsize, Ordering}, sys::thread_local_dtor::run_dtors, + thread::NativeOptions, time::Duration, }; @@ -83,7 +84,11 @@ impl Thread { /// # Safety /// /// See `thread::Builder::spawn_unchecked` for safety requirements. - pub unsafe fn new(stack: usize, p: Box) -> io::Result { + pub unsafe fn new( + stack: usize, + p: Box, + _native_options: NativeOptions, + ) -> io::Result { let inner = Box::new(ThreadInner { start: UnsafeCell::new(ManuallyDrop::new(p)), lifecycle: AtomicUsize::new(LIFECYCLE_INIT), @@ -288,6 +293,9 @@ impl Drop for Thread { } } +pub type Priority = (); +pub type Affinity = (); + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index d745a61961404..da7370b376809 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -3,6 +3,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; +use crate::thread::NativeOptions; use crate::time::Duration; use super::abi::usercalls; @@ -104,7 +105,11 @@ pub mod wait_notify { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, p: Box) -> io::Result { + pub unsafe fn new( + _stack: usize, + p: Box, + _native_options: NativeOptions, + ) -> io::Result { let mut queue_lock = task_queue::lock(); unsafe { usercalls::launch_thread()? }; let (task, handle) = task_queue::Task::new(p); @@ -137,6 +142,9 @@ impl Thread { } } +pub type Priority = (); +pub type Affinity = (); + pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index c1d30dd9d521b..7f6b6be6443e6 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -20,6 +20,19 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024; #[cfg(target_os = "espidf")] pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF menuconfig system should be used +cfg_if::cfg_if! { + if #[cfg(target_os = "horizon")] { + pub type Priority = crate::os::horizon::thread::Priority; + pub type Affinity = crate::os::horizon::thread::Affinity; + } else if #[cfg(target_os = "linux")] { + pub type Priority = crate::os::linux::thread::Priority; + pub type Affinity = crate::os::linux::thread::Affinity; + } else { + pub type Priority = (); + pub type Affinity = (); + } +} + #[cfg(target_os = "fuchsia")] mod zircon { type zx_handle_t = u32; @@ -48,7 +61,11 @@ unsafe impl Sync for Thread {} impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(stack: usize, p: Box) -> io::Result { + pub(crate) unsafe fn new( + stack: usize, + p: Box, + #[allow(unused)] native_options: crate::thread::NativeOptions, + ) -> io::Result { let p = Box::into_raw(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); @@ -84,6 +101,30 @@ impl Thread { }; } + #[cfg(any(target_os = "linux", target_os = "horizon"))] + { + if let Some(priority) = native_options.priority { + let sched_param = libc::sched_param { sched_priority: priority.0 }; + // NOTE: needs to be added to libc, for now this doesn't compile + // assert_eq!(libc::pthread_attr_setschedparam(&mut attr, &sched_param), 0); + } + + if let Some(affinity) = native_options.affinity { + #[cfg(target_os = "linux")] + assert_eq!( + libc::pthread_attr_setaffinity_np( + &mut attr, + mem::size_of::(), + &affinity.0, + ), + 0 + ); + + #[cfg(target_os = "horizon")] + assert_eq!(libc::pthread_attr_setprocessorid_np(&mut attr, affinity.0), 0); + } + } + let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); // Note: if the thread creation fails and this assert fails, then p will // be leaked. However, an alternative design could cause double-free @@ -213,7 +254,8 @@ impl Thread { target_os = "l4re", target_os = "emscripten", target_os = "redox", - target_os = "vxworks" + target_os = "vxworks", + target_os = "horizon" ))] pub fn set_name(_name: &CStr) { // Newlib, Emscripten, and VxWorks have no way to set a thread name. diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs index a8db251de2017..9797a5c1d9cc6 100644 --- a/library/std/src/sys/unsupported/thread.rs +++ b/library/std/src/sys/unsupported/thread.rs @@ -2,6 +2,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; +use crate::thread::NativeOptions; use crate::time::Duration; pub struct Thread(!); @@ -10,7 +11,11 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { + pub unsafe fn new( + _stack: usize, + _p: Box, + _native_options: NativeOptions, + ) -> io::Result { unsupported() } @@ -31,6 +36,9 @@ impl Thread { } } +pub type Priority = (); +pub type Affinity = (); + pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index e7a6ab4be826f..7b9a4eab5a652 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -5,6 +5,7 @@ use crate::io; use crate::mem; use crate::num::NonZeroUsize; use crate::sys::unsupported; +use crate::thread::NativeOptions; use crate::time::Duration; pub struct Thread(!); @@ -13,7 +14,11 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { + pub unsafe fn new( + _stack: usize, + _p: Box, + _native_options: NativeOptions, + ) -> io::Result { unsupported() } @@ -66,6 +71,9 @@ impl Thread { } } +pub type Priority = (); +pub type Affinity = (); + pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs index 714b704922794..48248750f9f22 100644 --- a/library/std/src/sys/wasm/atomics/thread.rs +++ b/library/std/src/sys/wasm/atomics/thread.rs @@ -2,6 +2,7 @@ use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; use crate::sys::unsupported; +use crate::thread::NativeOptions; use crate::time::Duration; pub struct Thread(!); @@ -10,7 +11,11 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { + pub unsafe fn new( + _stack: usize, + _p: Box, + _native_options: NativeOptions, + ) -> io::Result { unsupported() } @@ -40,6 +45,9 @@ impl Thread { pub fn join(self) {} } +pub type Priority = (); +pub type Affinity = (); + pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index c5c9e97e646fb..4120cd6e1cfb9 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -7,6 +7,7 @@ use crate::sys::c; use crate::sys::handle::Handle; use crate::sys::stack_overflow; use crate::sys_common::FromInner; +use crate::thread::NativeOptions; use crate::time::Duration; use libc::c_void; @@ -15,13 +16,20 @@ use super::to_u16s; pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; +pub type Priority = (); +pub type Affinity = (); + pub struct Thread { handle: Handle, } impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(stack: usize, p: Box) -> io::Result { + pub unsafe fn new( + stack: usize, + p: Box, + _native_options: NativeOptions, + ) -> io::Result { let p = Box::into_raw(box p); // FIXME On UNIX, we guard against stack sizes that are too small but @@ -98,6 +106,9 @@ impl Thread { } } +pub type Priority = (); +pub type Affinity = (); + pub fn available_parallelism() -> io::Result { let res = unsafe { let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed(); diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 34bdb8bd4612e..37092abdfab80 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -193,6 +193,11 @@ pub use scoped::{scope, Scope, ScopedJoinHandle}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::local::{AccessError, LocalKey}; +#[unstable(feature = "thread_scheduling", issue = "none")] +mod schedule; +#[unstable(feature = "thread_scheduling", issue = "none")] +pub use schedule::*; + // Provide the type used by the thread_local! macro to access TLS keys. This // needs to be kept in sync with the macro itself (in `local.rs`). // There are three types: "static", "fast", "OS". The "OS" thread local key @@ -232,6 +237,14 @@ pub use self::local::os::Key as __OsLocalKeyInner; #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; +#[derive(Debug, Default)] +pub(crate) struct NativeOptions { + /// The spawned thread's priority value + pub priority: Option, + /// The processor(s) to run the spawned thread on + pub affinity: Option, +} + //////////////////////////////////////////////////////////////////////////////// // Builder //////////////////////////////////////////////////////////////////////////////// @@ -286,6 +299,8 @@ pub struct Builder { name: Option, // The size of the stack for the spawned thread in bytes stack_size: Option, + // Other OS-specific fields. These can be set with helpers found in std::os. + native_options: NativeOptions, } impl Builder { @@ -309,7 +324,7 @@ impl Builder { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> Builder { - Builder { name: None, stack_size: None } + Builder { name: None, stack_size: None, native_options: NativeOptions::default() } } /// Names the thread-to-be. Currently the name is used for identification @@ -365,6 +380,18 @@ impl Builder { self } + #[unstable(feature = "thread_scheduling", issue = "none")] + pub fn priority(mut self, priority: Priority) -> Builder { + self.native_options.priority = Some(priority.into()); + self + } + + #[unstable(feature = "thread_scheduling", issue = "none")] + pub fn affinity(mut self, affinity: Affinity) -> Builder { + self.native_options.affinity = Some(affinity.into()); + self + } + /// Spawns a new thread by taking ownership of the `Builder`, and returns an /// [`io::Result`] to its [`JoinHandle`]. /// @@ -489,11 +516,9 @@ impl Builder { T: Send + 'a, 'scope: 'a, { - let Builder { name, stack_size } = self; - - let stack_size = stack_size.unwrap_or_else(thread::min_stack); + let stack_size = self.stack_size.unwrap_or_else(thread::min_stack); - let my_thread = Thread::new(name.map(|name| { + let my_thread = Thread::new(self.name.map(|name| { CString::new(name).expect("thread name may not contain interior null bytes") })); let their_thread = my_thread.clone(); @@ -586,6 +611,7 @@ impl Builder { mem::transmute::, Box>( Box::new(main), ), + self.native_options, )? }, thread: my_thread, diff --git a/library/std/src/thread/schedule.rs b/library/std/src/thread/schedule.rs new file mode 100644 index 0000000000000..ef970f3ad32de --- /dev/null +++ b/library/std/src/thread/schedule.rs @@ -0,0 +1,31 @@ +use super::imp; + +#[derive(Debug)] +pub struct Priority(imp::Priority); + +impl From for Priority { + fn from(priority: imp::Priority) -> Self { + Self(priority) + } +} + +impl From for imp::Priority { + fn from(priority: Priority) -> Self { + priority.0 + } +} + +#[derive(Debug)] +pub struct Affinity(pub(crate) imp::Affinity); + +impl From for Affinity { + fn from(affinity: imp::Affinity) -> Self { + Self(affinity) + } +} + +impl From for imp::Affinity { + fn from(affinity: Affinity) -> Self { + affinity.0 + } +} From d0ad7f6c53b7d7a2f16ca27afe837c567c731621 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sun, 27 Nov 2022 23:39:17 -0700 Subject: [PATCH 2/2] Add some documentation for the new APIs --- library/std/src/os/horizon/thread.rs | 12 ++++++++++++ library/std/src/os/linux/thread.rs | 27 ++++++++++++++++++++++++++- library/std/src/sys/unix/thread.rs | 4 ++-- library/std/src/thread/mod.rs | 6 ++++++ library/std/src/thread/schedule.rs | 21 +++++++++++++++++++++ 5 files changed, 67 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/horizon/thread.rs b/library/std/src/os/horizon/thread.rs index c3e6c92823e0f..7e8946ce193c2 100644 --- a/library/std/src/os/horizon/thread.rs +++ b/library/std/src/os/horizon/thread.rs @@ -1,7 +1,15 @@ +//! Horizon-specific extensions for working with the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread + #![unstable(feature = "thread_scheduling", issue = "none")] use crate::fmt; +/// The relative priority of the thread. See the `libctru` docs for the `prio` +/// parameter of [`threadCreate`] for details on valid values. +/// +/// [`threadCreate`]: https://libctru.devkitpro.org/thread_8h.html#a38c873d8cb02de7f5eca848fe68183ee pub struct Priority(pub(crate) libc::c_int); impl TryFrom for Priority { @@ -21,6 +29,10 @@ impl crate::fmt::Debug for Priority { } } +/// The CPU(s) on which to spawn the thread. See the `libctru` docs for the +/// `core_id` parameter of [`threadCreate`] for details on valid values. +/// +/// [`threadCreate`]: https://libctru.devkitpro.org/thread_8h.html#a38c873d8cb02de7f5eca848fe68183ee pub struct Affinity(pub(crate) libc::c_int); impl Default for Affinity { diff --git a/library/std/src/os/linux/thread.rs b/library/std/src/os/linux/thread.rs index 6606fcf8d445b..8bce3a9961be8 100644 --- a/library/std/src/os/linux/thread.rs +++ b/library/std/src/os/linux/thread.rs @@ -1,11 +1,22 @@ +//! Linux-specific extensions for working with the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread + #![unstable(feature = "thread_scheduling", issue = "none")] use crate::fmt; +/// The relative scheduling priority of a thread, corresponding to the +/// `sched_priority` scheduling parameter. +/// +/// Refer to the man page for [`pthread_attr_setschedparam(3)`] for more details. +/// +/// [`pthread_attr_setschedparam(3)`]: https://man7.org/linux/man-pages/man3/pthread_attr_setschedparam.3.html pub struct Priority(pub(crate) libc::c_int); impl Priority { - fn new(priority: i32) -> Self { + /// Create an integer priority. + pub fn new(priority: i32) -> Self { Self(priority) } } @@ -16,9 +27,19 @@ impl crate::fmt::Debug for Priority { } } +/// The CPU affinity mask of a thread, which determines what CPUs a thread is +/// eligible to run on. +/// +/// Refer to the man page for [`pthread_attr_setaffinity_np(3)`] for more details. +/// +/// [`pthread_attr_setaffinity_np(3)`]: https://man7.org/linux/man-pages/man3/pthread_attr_setaffinity_np.3.html pub struct Affinity(pub(crate) libc::cpu_set_t); impl Affinity { + /// Create an affinity mask with no CPUs in it. + /// See the man page entry for [`CPU_ZERO`] for more details. + /// + /// [`CPU_ZERO`]: https://man7.org/linux/man-pages/man3/CPU_SET.3.html pub fn new() -> Self { unsafe { let mut set = crate::mem::zeroed(); @@ -27,6 +48,10 @@ impl Affinity { } } + /// Add a CPU to the affinity mask. + /// See the man page entry for [`CPU_SET`] for more details. + /// + /// [`CPU_SET`]: https://man7.org/linux/man-pages/man3/CPU_SET.3.html pub fn set(&mut self, cpu: usize) { unsafe { libc::CPU_SET(cpu, &mut self.0); diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 7f6b6be6443e6..ccebddb33e8fe 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -104,8 +104,8 @@ impl Thread { #[cfg(any(target_os = "linux", target_os = "horizon"))] { if let Some(priority) = native_options.priority { - let sched_param = libc::sched_param { sched_priority: priority.0 }; - // NOTE: needs to be added to libc, for now this doesn't compile + let _sched_param = libc::sched_param { sched_priority: priority.0 }; + todo!("needs libc support for pthread_attr_setschedparam") // assert_eq!(libc::pthread_attr_setschedparam(&mut attr, &sched_param), 0); } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 37092abdfab80..62d530fb7705e 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -380,12 +380,18 @@ impl Builder { self } + /// Sets the priority of the new thread in a platform-specific way. + /// + /// See [`Priority`] for more details. #[unstable(feature = "thread_scheduling", issue = "none")] pub fn priority(mut self, priority: Priority) -> Builder { self.native_options.priority = Some(priority.into()); self } + /// Sets the CPU affinity of the new thread in a platform-specific way. + /// + /// See [`Affinity`] for more details. #[unstable(feature = "thread_scheduling", issue = "none")] pub fn affinity(mut self, affinity: Affinity) -> Builder { self.native_options.affinity = Some(affinity.into()); diff --git a/library/std/src/thread/schedule.rs b/library/std/src/thread/schedule.rs index ef970f3ad32de..6341ca4e63038 100644 --- a/library/std/src/thread/schedule.rs +++ b/library/std/src/thread/schedule.rs @@ -1,5 +1,15 @@ use super::imp; +/// The relative priority of an thread. The representation of this priority is +/// platform-dependent and setting priority may not be supported on all platforms. +/// +/// To set a thread's priority on supported platforms, use helpers in [`std::os`] +/// (e.g. [`os::linux::thread::Priority`]) to create a `thread::Priority` and +/// [`thread::Builder::priority`] to set the thread's priority. +/// +/// [`std::os`]: crate::os +/// [`os::linux::thread::Priority`]: crate::os::linux::thread::Priority +/// [`thread::Builder::priority`]: crate::thread::Builder::priority #[derive(Debug)] pub struct Priority(imp::Priority); @@ -15,6 +25,17 @@ impl From for imp::Priority { } } +/// The affinity of an thread, i.e. which CPU(s) a thread may run on. The +/// meaning and representation of a thread's affinity is platform-dependent +/// and setting affinity may not be supported on all platforms. +/// +/// To set a thread's affinity on supported platforms, use helpers from [`std::os`] +/// (e.g. [`os::linux::thread::Affinity`]) to create a `thread::Affinity` and +/// [`thread::Builder::affinity`] to set the thread's affinity. +/// +/// [`std::os`]: crate::os +/// [`os::linux::thread::Affinity`]: crate::os::linux::thread::Affinity +/// [`thread::Builder::affinity`]: crate::thread::Builder::affinity #[derive(Debug)] pub struct Affinity(pub(crate) imp::Affinity);