From 9063edaf3bcf3d0897ee3e73b6468c3984883b18 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Thu, 29 Apr 2021 11:40:14 +0200 Subject: Move `available_concurrency` implementation to `sys` --- library/std/src/sys/hermit/thread.rs | 8 +++ library/std/src/sys/sgx/thread.rs | 8 +++ library/std/src/sys/unix/thread.rs | 83 ++++++++++++++++++++++++++++++ library/std/src/sys/unsupported/thread.rs | 8 +++ library/std/src/sys/wasi/thread.rs | 8 +++ library/std/src/sys/wasm/atomics/thread.rs | 8 +++ library/std/src/sys/windows/c.rs | 18 +++++++ library/std/src/sys/windows/thread.rs | 16 ++++++ 8 files changed, 157 insertions(+) (limited to 'library/std/src/sys') diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index f35a3a8a80f..3d00e626e1a 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -3,6 +3,7 @@ use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::sys::hermit::abi; use crate::sys::hermit::thread_local_dtor::run_dtors; use crate::time::Duration; @@ -95,6 +96,13 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )) +} + 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 67e2e8b59d3..b82ae86521a 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -1,6 +1,7 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::time::Duration; use super::abi::usercalls; @@ -135,6 +136,13 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )) +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index b8f43caec32..e49971de940 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -2,6 +2,7 @@ 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; @@ -198,6 +199,88 @@ impl Drop for Thread { } } +pub fn available_concurrency() -> io::Result { + 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::NotFound, &"The number of hardware threads is not known for the target platform")) + } + } +} + #[cfg(all( not(target_os = "linux"), not(target_os = "freebsd"), diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs index cda8510e1ba..47005ead196 100644 --- a/library/std/src/sys/unsupported/thread.rs +++ b/library/std/src/sys/unsupported/thread.rs @@ -1,6 +1,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::time::Duration; pub struct Thread(!); @@ -30,6 +31,13 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )) +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index 74515553a82..959077f7b54 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -3,6 +3,7 @@ use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::sys::unsupported; use crate::time::Duration; @@ -63,6 +64,13 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )) +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs index 54bc877aa7d..8207a41035d 100644 --- a/library/std/src/sys/wasm/atomics/thread.rs +++ b/library/std/src/sys/wasm/atomics/thread.rs @@ -1,5 +1,6 @@ use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::sys::unsupported; use crate::time::Duration; @@ -39,6 +40,13 @@ impl Thread { pub fn join(self) {} } +pub fn available_concurrency() -> io::Result { + Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )) +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b64870401f1..193c28c7673 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -13,6 +13,7 @@ use libc::{c_void, size_t, wchar_t}; pub use self::EXCEPTION_DISPOSITION::*; pub use self::FILE_INFO_BY_HANDLE_CLASS::*; +pub type DWORD_PTR = ULONG_PTR; pub type DWORD = c_ulong; pub type NonZeroDWORD = NonZero_c_ulong; pub type HANDLE = LPVOID; @@ -53,6 +54,7 @@ pub type LPWSADATA = *mut WSADATA; pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; pub type LPWSTR = *mut WCHAR; pub type LPFILETIME = *mut FILETIME; +pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; pub type LPWSABUF = *mut WSABUF; pub type LPWSAOVERLAPPED = *mut c_void; pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void; @@ -533,6 +535,21 @@ pub struct FILETIME { pub dwHighDateTime: DWORD, } +#[repr(C)] +pub struct SYSTEM_INFO { + pub wProcessorArchitecture: WORD, + pub wReserved: WORD, + pub dwPageSize: DWORD, + pub lpMinimumApplicationAddress: LPVOID, + pub lpMaximumApplicationAddress: LPVOID, + pub dwActiveProcessorMask: DWORD_PTR, + pub dwNumberOfProcessors: DWORD, + pub dwProcessorType: DWORD, + pub dwAllocationGranularity: DWORD, + pub wProcessorLevel: WORD, + pub wProcessorRevision: WORD, +} + #[repr(C)] pub struct OVERLAPPED { pub Internal: *mut c_ulong, @@ -934,6 +951,7 @@ extern "system" { pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); + pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); pub fn CreateEventW( lpEventAttributes: LPSECURITY_ATTRIBUTES, diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index 38839ea5e90..ef7a9733fd8 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -1,5 +1,6 @@ use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; @@ -98,6 +99,21 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + let res = unsafe { + let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed(); + c::GetSystemInfo(&mut sysinfo); + sysinfo.dwNumberOfProcessors as usize + }; + match res { + 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) }), + } +} + #[cfg_attr(test, allow(dead_code))] pub mod guard { pub type Guard = !; -- cgit 1.4.1-3-g733a5