diff --git a/Cargo.toml b/Cargo.toml index f3778b9..cfc5bdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "num_cpus" version = "1.13.0" # don't forget to update html_root_url +edition = "2018" description = "Get the number of CPUs on a machine." authors = ["Sean McArthur "] license = "MIT OR Apache-2.0" @@ -10,6 +11,7 @@ documentation = "https://docs.rs/num_cpus" keywords = ["cpu", "cpus", "cores"] categories = ["hardware-support"] readme = "README.md" +include = ["src/**/*", "LICENSE-*", "README.md", "CHANGELOG.md"] [target.'cfg(not(windows))'.dependencies] libc = "0.2.26" diff --git a/README.md b/README.md index 1de7d8e..1a23b85 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ num_cpus = "1.0" In your `main.rs` or `lib.rs`: ```rust -extern crate num_cpus; +use num_cpus; // count logical cores this process could try to use let num = num_cpus::get(); diff --git a/examples/values.rs b/examples/values.rs index 041cfaf..ca00adf 100644 --- a/examples/values.rs +++ b/examples/values.rs @@ -1,4 +1,4 @@ -extern crate num_cpus; +use num_cpus; fn main() { println!("Logical CPUs: {}", num_cpus::get()); diff --git a/src/lib.rs b/src/lib.rs index 940fb3f..2c86b63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ //! 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 +//! [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. @@ -40,7 +40,7 @@ extern crate hermit_abi; #[cfg(target_os = "linux")] mod linux; #[cfg(target_os = "linux")] -use linux::{get_num_cpus, get_num_physical_cpus}; +use crate::linux::{get_num_cpus, get_num_physical_cpus}; /// Returns the number of available CPUs of the current system. /// @@ -93,7 +93,7 @@ pub fn get() -> usize { /// 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 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 \ @@ -110,8 +110,12 @@ pub fn get_physical() -> usize { get_num_physical_cpus() } - -#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos", target_os="openbsd")))] +#[cfg(not(any( + target_os = "linux", + target_os = "windows", + target_os = "macos", + target_os = "openbsd" +)))] #[inline] fn get_num_physical_cpus() -> usize { // Not implemented, fall back @@ -122,7 +126,7 @@ fn get_num_physical_cpus() -> usize { fn get_num_physical_cpus() -> usize { match get_num_physical_cpus_windows() { Some(num) => num, - None => get_num_cpus() + None => get_num_cpus(), } } @@ -130,8 +134,8 @@ fn get_num_physical_cpus() -> usize { fn get_num_physical_cpus_windows() -> Option { // Inspired by https://msdn.microsoft.com/en-us/library/ms683194 - use std::ptr; use std::mem; + use std::ptr; #[allow(non_upper_case_globals)] const RelationProcessorCore: u32 = 0; @@ -141,13 +145,13 @@ fn get_num_physical_cpus_windows() -> Option { struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION { mask: usize, relationship: u32, - _unused: [u64; 2] + _unused: [u64; 2], } extern "system" { fn GetLogicalProcessorInformation( info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION, - length: &mut u32 + length: &mut u32, ) -> u32; } @@ -189,7 +193,8 @@ fn get_num_physical_cpus_windows() -> Option { buf.set_len(count as usize); } - let phys_proc_count = buf.iter() + let phys_proc_count = buf + .iter() // Only interested in processor packages (physical processors.) .filter(|proc_info| proc_info.relationship == RelationProcessorCore) .count(); @@ -229,9 +234,7 @@ fn get_num_cpus() -> usize { } } -#[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "netbsd"))] +#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] fn get_num_cpus() -> usize { use std::ptr; @@ -244,12 +247,14 @@ fn get_num_cpus() -> usize { 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); + 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; @@ -268,12 +273,14 @@ fn get_num_cpus() -> usize { 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); + 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; @@ -291,12 +298,14 @@ fn get_num_physical_cpus() -> usize { 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); + 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; @@ -304,7 +313,6 @@ fn get_num_physical_cpus() -> usize { cpus as usize } - #[cfg(target_os = "macos")] fn get_num_physical_cpus() -> usize { use std::ffi::CStr; @@ -313,15 +321,17 @@ fn get_num_physical_cpus() -> usize { 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"); + 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) { + 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(); } } @@ -335,8 +345,8 @@ fn get_num_physical_cpus() -> usize { target_os = "android", target_os = "solaris", target_os = "illumos", - target_os = "fuchsia") -)] + 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. @@ -391,7 +401,7 @@ fn get_num_cpus() -> usize { pub abi: u32, } - extern { + extern "C" { fn get_system_info(info: *mut system_info) -> status_t; } diff --git a/src/linux.rs b/src/linux.rs index 671a943..36bd8fa 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -2,12 +2,11 @@ use std::collections::HashMap; use std::fs::File; use std::io::{BufRead, BufReader, Read}; use std::mem; +use std::mem::MaybeUninit; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Once; -use libc; - macro_rules! debug { ($($args:expr),*) => ({ if false { @@ -18,7 +17,7 @@ macro_rules! debug { } macro_rules! some { - ($e:expr) => ({ + ($e:expr) => {{ match $e { Some(v) => v, None => { @@ -26,7 +25,7 @@ macro_rules! some { return None; } } - }) + }}; } pub fn get_num_cpus() -> usize { @@ -37,12 +36,14 @@ pub fn get_num_cpus() -> usize { } fn logical_cpus() -> usize { - let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; - if unsafe { libc::sched_getaffinity(0, mem::size_of::(), &mut set) } == 0 { + let mut set = MaybeUninit::::uninit(); + if unsafe { libc::sched_getaffinity(0, mem::size_of::(), set.as_mut_ptr()) } + == 0 + { let mut count: u32 = 0; for i in 0..libc::CPU_SETSIZE as usize { - if unsafe { libc::CPU_ISSET(i, &set) } { - count += 1 + if unsafe { libc::CPU_ISSET(i, &set.as_ptr().read()) } { + count += 1; } } count as usize @@ -137,7 +138,7 @@ fn init_cgroups() { CGROUPS_CPUS.store(count, Ordering::SeqCst); } - None => return, + None => {} } } @@ -166,19 +167,15 @@ struct Subsys { } impl Cgroup { - fn new(dir: PathBuf) -> Cgroup { - Cgroup { - base: dir, - } + const fn new(dir: PathBuf) -> Self { + Self { base: dir } } - fn translate(mntinfo: MountInfo, subsys: Subsys) -> Option { + fn translate(mntinfo: MountInfo, subsys: Subsys) -> Option { // Translate the subsystem directory via the host paths. debug!( "subsys = {:?}; root = {:?}; mount_point = {:?}", - subsys.base, - mntinfo.root, - mntinfo.mount_point + subsys.base, mntinfo.root, mntinfo.mount_point ); let rel_from_root = some!(Path::new(&subsys.base).strip_prefix(&mntinfo.root).ok()); @@ -188,7 +185,7 @@ impl Cgroup { // join(mp.MountPoint, relPath) let mut path = PathBuf::from(mntinfo.mount_point); path.push(rel_from_root); - Some(Cgroup::new(path)) + Some(Self::new(path)) } fn cpu_quota(&self) -> Option { @@ -225,21 +222,20 @@ impl Cgroup { } impl MountInfo { - fn load_cpu>(proc_path: P) -> Option { + fn load_cpu>(proc_path: P) -> Option { let file = some!(File::open(proc_path).ok()); let file = BufReader::new(file); file.lines() - .filter_map(|result| result.ok()) - .filter_map(MountInfo::parse_line) - .next() + .filter_map(Result::ok) + .find_map(Self::parse_line) } - fn parse_line(line: String) -> Option { + fn parse_line(line: String) -> Option { let mut fields = line.split(' '); let mnt_root = some!(fields.nth(3)); - let mnt_point = some!(fields.nth(0)); + let mnt_point = some!(fields.next()); if fields.nth(3) != Some("cgroup") { return None; @@ -252,7 +248,7 @@ impl MountInfo { return None; } - Some(MountInfo { + Some(Self { root: mnt_root.to_owned(), mount_point: mnt_point.to_owned(), }) @@ -260,17 +256,16 @@ impl MountInfo { } impl Subsys { - fn load_cpu>(proc_path: P) -> Option { + fn load_cpu>(proc_path: P) -> Option { let file = some!(File::open(proc_path).ok()); let file = BufReader::new(file); file.lines() - .filter_map(|result| result.ok()) - .filter_map(Subsys::parse_line) - .next() + .filter_map(std::result::Result::ok) + .find_map(Self::parse_line) } - fn parse_line(line: String) -> Option { + fn parse_line(line: String) -> Option { // Example format: // 11:cpu,cpuacct:/ let mut fields = line.split(':'); @@ -281,19 +276,20 @@ impl Subsys { return None; } - fields.next().map(|path| Subsys { base: path.to_owned() }) + fields.next().map(|path| Self { + base: path.to_string(), + }) } } #[cfg(test)] mod tests { - use std::path::{Path, PathBuf}; use super::{Cgroup, MountInfo, Subsys}; + use std::path::{Path, PathBuf}; + static FIXTURES_PROC: &str = "fixtures/cgroups/proc/cgroups"; - static FIXTURES_PROC: &'static str = "fixtures/cgroups/proc/cgroups"; - - static FIXTURES_CGROUPS: &'static str = "fixtures/cgroups/cgroups"; + static FIXTURES_CGROUPS: &str = "fixtures/cgroups/cgroups"; macro_rules! join { ($base:expr, $($path:expr),+) => ({ @@ -324,12 +320,7 @@ mod tests { #[test] fn test_cgroup_mount() { let cases = &[ - ( - "/", - "/sys/fs/cgroup/cpu", - "/", - Some("/sys/fs/cgroup/cpu"), - ), + ("/", "/sys/fs/cgroup/cpu", "/", Some("/sys/fs/cgroup/cpu")), ( "/docker/01abcd", "/sys/fs/cgroup/cpu", @@ -348,27 +339,10 @@ mod tests { "/docker/01abcd/large", Some("/sys/fs/cgroup/cpu/large"), ), - // fails - - ( - "/docker/01abcd", - "/sys/fs/cgroup/cpu", - "/", - None, - ), - ( - "/docker/01abcd", - "/sys/fs/cgroup/cpu", - "/docker", - None, - ), - ( - "/docker/01abcd", - "/sys/fs/cgroup/cpu", - "/elsewhere", - None, - ), + ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/", None), + ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/docker", None), + ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/elsewhere", None), ( "/docker/01abcd", "/sys/fs/cgroup/cpu", @@ -387,7 +361,7 @@ mod tests { }; let actual = Cgroup::translate(mnt_info, subsys).map(|c| c.base); - let expected = expected.map(|s| PathBuf::from(s)); + let expected = expected.map(PathBuf::from); assert_eq!(actual, expected); } }