Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
485
third-party/vendor/num_cpus/src/lib.rs
vendored
Normal file
485
third-party/vendor/num_cpus/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,485 @@
|
|||
//! A crate with utilities to determine the number of CPUs available on the
|
||||
//! current system.
|
||||
//!
|
||||
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
|
||||
//! [processor tricks] to deliver increased performance when there are more threads. This
|
||||
//! crate provides methods to get both the logical and physical numbers of cores.
|
||||
//!
|
||||
//! This information can be used as a guide to how many tasks can be run in parallel.
|
||||
//! There are many properties of the system architecture that will affect parallelism,
|
||||
//! for example memory access speeds (for all the caches and RAM) and the physical
|
||||
//! architecture of the processor, so the number of CPUs should be used as a rough guide
|
||||
//! only.
|
||||
//!
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! Fetch the number of logical CPUs.
|
||||
//!
|
||||
//! ```
|
||||
//! let cpus = num_cpus::get();
|
||||
//! ```
|
||||
//!
|
||||
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
|
||||
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
|
||||
//! number 8, it could use the number of CPUs).
|
||||
//!
|
||||
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
|
||||
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/1.*/rayon/struct.ThreadPool.html
|
||||
#![cfg_attr(test, deny(warnings))]
|
||||
#![deny(missing_docs)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
#[cfg(not(windows))]
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
extern crate hermit_abi;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod linux;
|
||||
#[cfg(target_os = "linux")]
|
||||
use linux::{get_num_cpus, get_num_physical_cpus};
|
||||
|
||||
/// Returns the number of available CPUs of the current system.
|
||||
///
|
||||
/// This function will get the number of logical cores. Sometimes this is different from the number
|
||||
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
|
||||
///
|
||||
/// This will always return at least `1`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let cpus = num_cpus::get();
|
||||
/// if cpus > 1 {
|
||||
/// println!("We are on a multicore system with {} CPUs", cpus);
|
||||
/// } else {
|
||||
/// println!("We are on a single core system");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
|
||||
/// thread does not have access to all the computer's CPUs.
|
||||
///
|
||||
/// This will also check [cgroups], frequently used in containers to constrain CPU usage.
|
||||
///
|
||||
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
|
||||
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
|
||||
/// [cgroups]: https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
|
||||
#[inline]
|
||||
pub fn get() -> usize {
|
||||
get_num_cpus()
|
||||
}
|
||||
|
||||
/// Returns the number of physical cores of the current system.
|
||||
///
|
||||
/// This will always return at least `1`.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Physical count is supported only on Linux, mac OS and Windows platforms.
|
||||
/// On other platforms, or if the physical count fails on supported platforms,
|
||||
/// this function returns the same as [`get()`], which is the number of logical
|
||||
/// CPUS.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let logical_cpus = num_cpus::get();
|
||||
/// let physical_cpus = num_cpus::get_physical();
|
||||
/// if logical_cpus > physical_cpus {
|
||||
/// println!("We have simultaneous multithreading with about {:.2} \
|
||||
/// logical cores to 1 physical core.",
|
||||
/// (logical_cpus as f64) / (physical_cpus as f64));
|
||||
/// } else if logical_cpus == physical_cpus {
|
||||
/// println!("Either we don't have simultaneous multithreading, or our \
|
||||
/// system doesn't support getting the number of physical CPUs.");
|
||||
/// } else {
|
||||
/// println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
|
||||
/// some of the CPUs on our system.");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`get()`]: fn.get.html
|
||||
#[inline]
|
||||
pub fn get_physical() -> usize {
|
||||
get_num_physical_cpus()
|
||||
}
|
||||
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "linux",
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "openbsd",
|
||||
target_os = "aix")))]
|
||||
#[inline]
|
||||
fn get_num_physical_cpus() -> usize {
|
||||
// Not implemented, fall back
|
||||
get_num_cpus()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn get_num_physical_cpus() -> usize {
|
||||
match get_num_physical_cpus_windows() {
|
||||
Some(num) => num,
|
||||
None => get_num_cpus()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn get_num_physical_cpus_windows() -> Option<usize> {
|
||||
// Inspired by https://msdn.microsoft.com/en-us/library/ms683194
|
||||
|
||||
use std::ptr;
|
||||
use std::mem;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
const RelationProcessorCore: u32 = 0;
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
|
||||
mask: usize,
|
||||
relationship: u32,
|
||||
_unused: [u64; 2]
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
fn GetLogicalProcessorInformation(
|
||||
info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
|
||||
length: &mut u32
|
||||
) -> u32;
|
||||
}
|
||||
|
||||
// First we need to determine how much space to reserve.
|
||||
|
||||
// The required size of the buffer, in bytes.
|
||||
let mut needed_size = 0;
|
||||
|
||||
unsafe {
|
||||
GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
|
||||
}
|
||||
|
||||
let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;
|
||||
|
||||
// Could be 0, or some other bogus size.
|
||||
if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let count = needed_size / struct_size;
|
||||
|
||||
// Allocate some memory where we will store the processor info.
|
||||
let mut buf = Vec::with_capacity(count as usize);
|
||||
|
||||
let result;
|
||||
|
||||
unsafe {
|
||||
result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
|
||||
}
|
||||
|
||||
// Failed for any reason.
|
||||
if result == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let count = needed_size / struct_size;
|
||||
|
||||
unsafe {
|
||||
buf.set_len(count as usize);
|
||||
}
|
||||
|
||||
let phys_proc_count = buf.iter()
|
||||
// Only interested in processor packages (physical processors.)
|
||||
.filter(|proc_info| proc_info.relationship == RelationProcessorCore)
|
||||
.count();
|
||||
|
||||
if phys_proc_count == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(phys_proc_count)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn get_num_cpus() -> usize {
|
||||
#[repr(C)]
|
||||
struct SYSTEM_INFO {
|
||||
wProcessorArchitecture: u16,
|
||||
wReserved: u16,
|
||||
dwPageSize: u32,
|
||||
lpMinimumApplicationAddress: *mut u8,
|
||||
lpMaximumApplicationAddress: *mut u8,
|
||||
dwActiveProcessorMask: *mut u8,
|
||||
dwNumberOfProcessors: u32,
|
||||
dwProcessorType: u32,
|
||||
dwAllocationGranularity: u32,
|
||||
wProcessorLevel: u16,
|
||||
wProcessorRevision: u16,
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut sysinfo: SYSTEM_INFO = std::mem::zeroed();
|
||||
GetSystemInfo(&mut sysinfo);
|
||||
sysinfo.dwNumberOfProcessors as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "netbsd"))]
|
||||
fn get_num_cpus() -> usize {
|
||||
use std::ptr;
|
||||
|
||||
let mut cpus: libc::c_uint = 0;
|
||||
let mut cpus_size = std::mem::size_of_val(&cpus);
|
||||
|
||||
unsafe {
|
||||
cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
|
||||
}
|
||||
if cpus < 1 {
|
||||
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
|
||||
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);
|
||||
}
|
||||
if cpus < 1 {
|
||||
cpus = 1;
|
||||
}
|
||||
}
|
||||
cpus as usize
|
||||
}
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
fn get_num_cpus() -> usize {
|
||||
use std::ptr;
|
||||
|
||||
let mut cpus: libc::c_uint = 0;
|
||||
let mut cpus_size = std::mem::size_of_val(&cpus);
|
||||
let mut mib = [libc::CTL_HW, libc::HW_NCPUONLINE, 0, 0];
|
||||
let rc: libc::c_int;
|
||||
|
||||
unsafe {
|
||||
rc = libc::sysctl(mib.as_mut_ptr(),
|
||||
2,
|
||||
&mut cpus as *mut _ as *mut _,
|
||||
&mut cpus_size as *mut _ as *mut _,
|
||||
ptr::null_mut(),
|
||||
0);
|
||||
}
|
||||
if rc < 0 {
|
||||
cpus = 1;
|
||||
}
|
||||
cpus as usize
|
||||
}
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
fn get_num_physical_cpus() -> usize {
|
||||
use std::ptr;
|
||||
|
||||
let mut cpus: libc::c_uint = 0;
|
||||
let mut cpus_size = std::mem::size_of_val(&cpus);
|
||||
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
|
||||
let rc: libc::c_int;
|
||||
|
||||
unsafe {
|
||||
rc = libc::sysctl(mib.as_mut_ptr(),
|
||||
2,
|
||||
&mut cpus as *mut _ as *mut _,
|
||||
&mut cpus_size as *mut _ as *mut _,
|
||||
ptr::null_mut(),
|
||||
0);
|
||||
}
|
||||
if rc < 0 {
|
||||
cpus = 1;
|
||||
}
|
||||
cpus as usize
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_num_physical_cpus() -> usize {
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
|
||||
let mut cpus: i32 = 0;
|
||||
let mut cpus_size = std::mem::size_of_val(&cpus);
|
||||
|
||||
let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
|
||||
.expect("byte literal is missing NUL");
|
||||
|
||||
unsafe {
|
||||
if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
|
||||
&mut cpus as *mut _ as *mut _,
|
||||
&mut cpus_size as *mut _ as *mut _,
|
||||
ptr::null_mut(),
|
||||
0) {
|
||||
return get_num_cpus();
|
||||
}
|
||||
}
|
||||
cpus as usize
|
||||
}
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
fn get_num_physical_cpus() -> usize {
|
||||
match get_smt_threads_aix() {
|
||||
Some(num) => get_num_cpus() / num,
|
||||
None => get_num_cpus(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
fn get_smt_threads_aix() -> Option<usize> {
|
||||
let smt = unsafe {
|
||||
libc::getsystemcfg(libc::SC_SMT_TC)
|
||||
};
|
||||
if smt == u64::MAX {
|
||||
return None;
|
||||
}
|
||||
Some(smt as usize)
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "nacl",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "android",
|
||||
target_os = "aix",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia")
|
||||
)]
|
||||
fn get_num_cpus() -> usize {
|
||||
// On ARM targets, processors could be turned off to save power.
|
||||
// Use `_SC_NPROCESSORS_CONF` to get the real number.
|
||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||
const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
|
||||
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
|
||||
const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;
|
||||
|
||||
let cpus = unsafe { libc::sysconf(CONF_NAME) };
|
||||
if cpus < 1 {
|
||||
1
|
||||
} else {
|
||||
cpus as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "haiku")]
|
||||
fn get_num_cpus() -> usize {
|
||||
use std::mem;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type bigtime_t = i64;
|
||||
#[allow(non_camel_case_types)]
|
||||
type status_t = i32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct system_info {
|
||||
pub boot_time: bigtime_t,
|
||||
pub cpu_count: u32,
|
||||
pub max_pages: u64,
|
||||
pub used_pages: u64,
|
||||
pub cached_pages: u64,
|
||||
pub block_cache_pages: u64,
|
||||
pub ignored_pages: u64,
|
||||
pub needed_memory: u64,
|
||||
pub free_memory: u64,
|
||||
pub max_swap_pages: u64,
|
||||
pub free_swap_pages: u64,
|
||||
pub page_faults: u32,
|
||||
pub max_sems: u32,
|
||||
pub used_sems: u32,
|
||||
pub max_ports: u32,
|
||||
pub used_ports: u32,
|
||||
pub max_threads: u32,
|
||||
pub used_threads: u32,
|
||||
pub max_teams: u32,
|
||||
pub used_teams: u32,
|
||||
pub kernel_name: [::std::os::raw::c_char; 256usize],
|
||||
pub kernel_build_date: [::std::os::raw::c_char; 32usize],
|
||||
pub kernel_build_time: [::std::os::raw::c_char; 32usize],
|
||||
pub kernel_version: i64,
|
||||
pub abi: u32,
|
||||
}
|
||||
|
||||
extern {
|
||||
fn get_system_info(info: *mut system_info) -> status_t;
|
||||
}
|
||||
|
||||
let mut info: system_info = unsafe { mem::zeroed() };
|
||||
let status = unsafe { get_system_info(&mut info as *mut _) };
|
||||
if status == 0 {
|
||||
info.cpu_count as usize
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
fn get_num_cpus() -> usize {
|
||||
unsafe { hermit_abi::get_processor_count() }
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "nacl",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "android",
|
||||
target_os = "aix",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "openbsd",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "netbsd",
|
||||
target_os = "haiku",
|
||||
target_os = "hermit",
|
||||
windows,
|
||||
)))]
|
||||
fn get_num_cpus() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn env_var(name: &'static str) -> Option<usize> {
|
||||
::std::env::var(name).ok().map(|val| val.parse().unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get() {
|
||||
let num = super::get();
|
||||
if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
|
||||
assert_eq!(num, n);
|
||||
} else {
|
||||
assert!(num > 0);
|
||||
assert!(num < 236_451);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_physical() {
|
||||
let num = super::get_physical();
|
||||
if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
|
||||
assert_eq!(num, n);
|
||||
} else {
|
||||
assert!(num > 0);
|
||||
assert!(num < 236_451);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue