Move available_concurrency
implementation to sys
This commit is contained in:
parent
3824017f8e
commit
9063edaf3b
10 changed files with 194 additions and 162 deletions
|
@ -3,6 +3,7 @@
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::sys::hermit::abi;
|
use crate::sys::hermit::abi;
|
||||||
use crate::sys::hermit::thread_local_dtor::run_dtors;
|
use crate::sys::hermit::thread_local_dtor::run_dtors;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
@ -95,6 +96,13 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
Err(io::Error::new_const(
|
||||||
|
io::ErrorKind::NotFound,
|
||||||
|
&"The number of hardware threads is not known for the target platform",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
|
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
use super::abi::usercalls;
|
use super::abi::usercalls;
|
||||||
|
@ -135,6 +136,13 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
Err(io::Error::new_const(
|
||||||
|
io::ErrorKind::NotFound,
|
||||||
|
&"The number of hardware threads is not known for the target platform",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::cmp;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
use crate::sys::{os, stack_overflow};
|
use crate::sys::{os, stack_overflow};
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
@ -198,6 +199,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::NotFound, &"The number of hardware threads is not known for the target platform"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(target_os = "linux"),
|
not(target_os = "linux"),
|
||||||
not(target_os = "freebsd"),
|
not(target_os = "freebsd"),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use super::unsupported;
|
use super::unsupported;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
pub struct Thread(!);
|
pub struct Thread(!);
|
||||||
|
@ -30,6 +31,13 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
Err(io::Error::new_const(
|
||||||
|
io::ErrorKind::NotFound,
|
||||||
|
&"The number of hardware threads is not known for the target platform",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
@ -63,6 +64,13 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
Err(io::Error::new_const(
|
||||||
|
io::ErrorKind::NotFound,
|
||||||
|
&"The number of hardware threads is not known for the target platform",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
@ -39,6 +40,13 @@ impl Thread {
|
||||||
pub fn join(self) {}
|
pub fn join(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
Err(io::Error::new_const(
|
||||||
|
io::ErrorKind::NotFound,
|
||||||
|
&"The number of hardware threads is not known for the target platform",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -13,6 +13,7 @@ use libc::{c_void, size_t, wchar_t};
|
||||||
pub use self::EXCEPTION_DISPOSITION::*;
|
pub use self::EXCEPTION_DISPOSITION::*;
|
||||||
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
|
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
|
||||||
|
|
||||||
|
pub type DWORD_PTR = ULONG_PTR;
|
||||||
pub type DWORD = c_ulong;
|
pub type DWORD = c_ulong;
|
||||||
pub type NonZeroDWORD = NonZero_c_ulong;
|
pub type NonZeroDWORD = NonZero_c_ulong;
|
||||||
pub type HANDLE = LPVOID;
|
pub type HANDLE = LPVOID;
|
||||||
|
@ -53,6 +54,7 @@ pub type LPWSADATA = *mut WSADATA;
|
||||||
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
|
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
|
||||||
pub type LPWSTR = *mut WCHAR;
|
pub type LPWSTR = *mut WCHAR;
|
||||||
pub type LPFILETIME = *mut FILETIME;
|
pub type LPFILETIME = *mut FILETIME;
|
||||||
|
pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
|
||||||
pub type LPWSABUF = *mut WSABUF;
|
pub type LPWSABUF = *mut WSABUF;
|
||||||
pub type LPWSAOVERLAPPED = *mut c_void;
|
pub type LPWSAOVERLAPPED = *mut c_void;
|
||||||
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
|
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
|
||||||
|
@ -533,6 +535,21 @@ pub struct FILETIME {
|
||||||
pub dwHighDateTime: DWORD,
|
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)]
|
#[repr(C)]
|
||||||
pub struct OVERLAPPED {
|
pub struct OVERLAPPED {
|
||||||
pub Internal: *mut c_ulong,
|
pub Internal: *mut c_ulong,
|
||||||
|
@ -934,6 +951,7 @@ extern "system" {
|
||||||
pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
|
pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
|
||||||
|
|
||||||
pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
|
pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
|
||||||
|
pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
|
||||||
|
|
||||||
pub fn CreateEventW(
|
pub fn CreateEventW(
|
||||||
lpEventAttributes: LPSECURITY_ATTRIBUTES,
|
lpEventAttributes: LPSECURITY_ATTRIBUTES,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
use crate::sys::c;
|
use crate::sys::c;
|
||||||
use crate::sys::handle::Handle;
|
use crate::sys::handle::Handle;
|
||||||
|
@ -98,6 +99,21 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
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))]
|
#[cfg_attr(test, allow(dead_code))]
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
use crate::io;
|
|
||||||
use crate::num::NonZeroUsize;
|
|
||||||
|
|
||||||
/// Returns the number of hardware threads available to the program.
|
|
||||||
///
|
|
||||||
/// This value should be considered only a hint.
|
|
||||||
///
|
|
||||||
/// # Platform-specific behavior
|
|
||||||
///
|
|
||||||
/// If interpreted as the number of actual hardware threads, it may undercount on
|
|
||||||
/// Windows systems with more than 64 hardware threads. If interpreted as the
|
|
||||||
/// available concurrency for that process, it may overcount on Windows systems
|
|
||||||
/// when limited by a process wide affinity mask or job object limitations, and
|
|
||||||
/// it may overcount on Linux systems when limited by a process wide affinity
|
|
||||||
/// mask or affected by cgroups limits.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// This function will return an error in the following situations, but is not
|
|
||||||
/// limited to just these cases:
|
|
||||||
///
|
|
||||||
/// - If the number of hardware threads is not known for the target platform.
|
|
||||||
/// - The process lacks permissions to view the number of hardware threads
|
|
||||||
/// available.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![allow(dead_code)]
|
|
||||||
/// #![feature(available_concurrency)]
|
|
||||||
/// use std::thread;
|
|
||||||
///
|
|
||||||
/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1);
|
|
||||||
/// ```
|
|
||||||
#[unstable(feature = "available_concurrency", issue = "74479")]
|
|
||||||
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
|
||||||
available_concurrency_internal()
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(windows)] {
|
|
||||||
#[allow(nonstandard_style)]
|
|
||||||
fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
|
|
||||||
#[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(info: *mut SYSTEM_INFO) -> i32;
|
|
||||||
}
|
|
||||||
let res = unsafe {
|
|
||||||
let mut sysinfo = crate::mem::zeroed();
|
|
||||||
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) }),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else 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",
|
|
||||||
))] {
|
|
||||||
fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
|
|
||||||
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"))] {
|
|
||||||
fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
|
|
||||||
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")] {
|
|
||||||
fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
|
|
||||||
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, HermitCore, Haiku, l4re
|
|
||||||
fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
|
|
||||||
Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -155,6 +155,7 @@ use crate::fmt;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::num::NonZeroU64;
|
use crate::num::NonZeroU64;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::panic;
|
use crate::panic;
|
||||||
use crate::panicking;
|
use crate::panicking;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
|
@ -174,15 +175,9 @@ use crate::time::Duration;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod local;
|
mod local;
|
||||||
|
|
||||||
#[unstable(feature = "available_concurrency", issue = "74479")]
|
|
||||||
mod available_concurrency;
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::local::{AccessError, LocalKey};
|
pub use self::local::{AccessError, LocalKey};
|
||||||
|
|
||||||
#[unstable(feature = "available_concurrency", issue = "74479")]
|
|
||||||
pub use available_concurrency::available_concurrency;
|
|
||||||
|
|
||||||
// The types used by the thread_local! macro to access TLS keys. Note that there
|
// The types used by the thread_local! macro to access TLS keys. Note that there
|
||||||
// are two types, the "OS" type and the "fast" type. The OS thread local key
|
// are two types, the "OS" type and the "fast" type. The OS thread local key
|
||||||
// type is accessed via platform-specific API calls and is slow, while the fast
|
// type is accessed via platform-specific API calls and is slow, while the fast
|
||||||
|
@ -1422,3 +1417,39 @@ fn _assert_sync_and_send() {
|
||||||
_assert_both::<JoinHandle<()>>();
|
_assert_both::<JoinHandle<()>>();
|
||||||
_assert_both::<Thread>();
|
_assert_both::<Thread>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of hardware threads available to the program.
|
||||||
|
///
|
||||||
|
/// This value should be considered only a hint.
|
||||||
|
///
|
||||||
|
/// # Platform-specific behavior
|
||||||
|
///
|
||||||
|
/// If interpreted as the number of actual hardware threads, it may undercount on
|
||||||
|
/// Windows systems with more than 64 hardware threads. If interpreted as the
|
||||||
|
/// available concurrency for that process, it may overcount on Windows systems
|
||||||
|
/// when limited by a process wide affinity mask or job object limitations, and
|
||||||
|
/// it may overcount on Linux systems when limited by a process wide affinity
|
||||||
|
/// mask or affected by cgroups limits.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// This function will return an error in the following situations, but is not
|
||||||
|
/// limited to just these cases:
|
||||||
|
///
|
||||||
|
/// - If the number of hardware threads is not known for the target platform.
|
||||||
|
/// - The process lacks permissions to view the number of hardware threads
|
||||||
|
/// available.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![allow(dead_code)]
|
||||||
|
/// #![feature(available_concurrency)]
|
||||||
|
/// use std::thread;
|
||||||
|
///
|
||||||
|
/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "available_concurrency", issue = "74479")]
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
imp::available_concurrency()
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue