diff options
Diffstat (limited to 'library/std/src/sys/unix/thread.rs')
| -rw-r--r-- | library/std/src/sys/unix/thread.rs | 193 |
1 files changed, 170 insertions, 23 deletions
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index b8f43caec32..133ad3ea420 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -2,16 +2,38 @@ use crate::cmp; use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::ptr; use crate::sys::{os, stack_overflow}; use crate::time::Duration; -#[cfg(not(any(target_os = "l4re", target_os = "vxworks")))] +#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))] +use crate::sys::weak::weak; +#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; #[cfg(target_os = "l4re")] pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; #[cfg(target_os = "vxworks")] 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(target_os = "fuchsia")] +mod zircon { + type zx_handle_t = u32; + type zx_status_t = i32; + pub const ZX_PROP_NAME: u32 = 3; + + extern "C" { + pub fn zx_object_set_property( + handle: zx_handle_t, + property: u32, + value: *const libc::c_void, + value_size: libc::size_t, + ) -> zx_status_t; + pub fn zx_thread_self() -> zx_handle_t; + } +} pub struct Thread { id: libc::pthread_t, @@ -30,22 +52,35 @@ impl Thread { let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); - let stack_size = cmp::max(stack, min_stack_size(&attr)); - - match libc::pthread_attr_setstacksize(&mut attr, stack_size) { - 0 => {} - n => { - assert_eq!(n, libc::EINVAL); - // EINVAL means |stack_size| is either too small or not a - // multiple of the system page size. Because it's definitely - // >= PTHREAD_STACK_MIN, it must be an alignment issue. - // Round up to the nearest page and try again. - let page_size = os::page_size(); - let stack_size = - (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); - assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); - } - }; + #[cfg(target_os = "espidf")] + if stack > 0 { + // Only set the stack if a non-zero value is passed + // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used + assert_eq!( + libc::pthread_attr_setstacksize(&mut attr, cmp::max(stack, min_stack_size(&attr))), + 0 + ); + } + + #[cfg(not(target_os = "espidf"))] + { + let stack_size = cmp::max(stack, min_stack_size(&attr)); + + match libc::pthread_attr_setstacksize(&mut attr, stack_size) { + 0 => {} + n => { + assert_eq!(n, libc::EINVAL); + // EINVAL means |stack_size| is either too small or not a + // multiple of the system page size. Because it's definitely + // >= PTHREAD_STACK_MIN, it must be an alignment issue. + // Round up to the nearest page and try again. + let page_size = os::page_size(); + let stack_size = + (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); + assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 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 @@ -131,22 +166,39 @@ impl Thread { } } + #[cfg(target_os = "fuchsia")] + pub fn set_name(name: &CStr) { + use self::zircon::*; + unsafe { + zx_object_set_property( + zx_thread_self(), + ZX_PROP_NAME, + name.as_ptr() as *const libc::c_void, + name.to_bytes().len(), + ); + } + } + + #[cfg(target_os = "haiku")] + pub fn set_name(name: &CStr) { + unsafe { + let thread_self = libc::find_thread(ptr::null_mut()); + libc::rename_thread(thread_self, name.as_ptr()); + } + } + #[cfg(any( target_env = "newlib", - target_os = "haiku", target_os = "l4re", target_os = "emscripten", target_os = "redox", target_os = "vxworks" ))] pub fn set_name(_name: &CStr) { - // Newlib, Haiku, Emscripten, and VxWorks have no way to set a thread name. - } - #[cfg(target_os = "fuchsia")] - pub fn set_name(_name: &CStr) { - // FIXME: determine whether Fuchsia has a way to set a thread name. + // Newlib, Emscripten, and VxWorks have no way to set a thread name. } + #[cfg(not(target_os = "espidf"))] pub fn sleep(dur: Duration) { let mut secs = dur.as_secs(); let mut nsecs = dur.subsec_nanos() as _; @@ -172,6 +224,19 @@ impl Thread { } } + #[cfg(target_os = "espidf")] + pub fn sleep(dur: Duration) { + let mut micros = dur.as_micros(); + unsafe { + while micros > 0 { + let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 }; + libc::usleep(st); + + micros -= st as u128; + } + } + } + pub fn join(self) { unsafe { let ret = libc::pthread_join(self.id, ptr::null_mut()); @@ -198,6 +263,88 @@ impl Drop for Thread { } } +pub fn available_concurrency() -> io::Result<NonZeroUsize> { + cfg_if::cfg_if! { + if #[cfg(any( + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "solaris", + target_os = "illumos", + ))] { + match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { + -1 => Err(io::Error::last_os_error()), + 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), + cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), + } + } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { + use crate::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = crate::mem::size_of_val(&cpus); + + unsafe { + cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; + } + + // Fallback approach in case of errors or no hardware threads. + if cpus < 1 { + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut cpus as *mut _ as *mut _, + &mut cpus_size as *mut _ as *mut _, + ptr::null_mut(), + 0, + ) + }; + + // Handle errors if any. + if res == -1 { + return Err(io::Error::last_os_error()); + } else if cpus == 0 { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + } + Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "openbsd")] { + use crate::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = crate::mem::size_of_val(&cpus); + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut cpus as *mut _ as *mut _, + &mut cpus_size as *mut _ as *mut _, + ptr::null_mut(), + 0, + ) + }; + + // Handle errors if any. + if res == -1 { + return Err(io::Error::last_os_error()); + } else if cpus == 0 { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + + Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else { + // FIXME: implement on vxWorks, Redox, Haiku, l4re + Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform")) + } + } +} + #[cfg(all( not(target_os = "linux"), not(target_os = "freebsd"), |
