@@ -2,6 +2,7 @@ use crate::cmp;
22use crate :: ffi:: CStr ;
33use crate :: io;
44use crate :: mem;
5+ use crate :: num:: NonZeroUsize ;
56use crate :: ptr;
67use crate :: sys:: { os, stack_overflow} ;
78use crate :: time:: Duration ;
@@ -198,6 +199,88 @@ impl Drop for Thread {
198199 }
199200}
200201
202+ pub fn available_concurrency ( ) -> io:: Result < NonZeroUsize > {
203+ cfg_if:: cfg_if! {
204+ if #[ cfg( any(
205+ target_os = "android" ,
206+ target_os = "emscripten" ,
207+ target_os = "fuchsia" ,
208+ target_os = "ios" ,
209+ target_os = "linux" ,
210+ target_os = "macos" ,
211+ target_os = "solaris" ,
212+ target_os = "illumos" ,
213+ ) ) ] {
214+ match unsafe { libc:: sysconf( libc:: _SC_NPROCESSORS_ONLN) } {
215+ -1 => Err ( io:: Error :: last_os_error( ) ) ,
216+ 0 => Err ( io:: Error :: new_const( io:: ErrorKind :: NotFound , & "The number of hardware threads is not known for the target platform" ) ) ,
217+ cpus => Ok ( unsafe { NonZeroUsize :: new_unchecked( cpus as usize ) } ) ,
218+ }
219+ } else if #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" , target_os = "netbsd" ) ) ] {
220+ use crate :: ptr;
221+
222+ let mut cpus: libc:: c_uint = 0 ;
223+ let mut cpus_size = crate :: mem:: size_of_val( & cpus) ;
224+
225+ unsafe {
226+ cpus = libc:: sysconf( libc:: _SC_NPROCESSORS_ONLN) as libc:: c_uint;
227+ }
228+
229+ // Fallback approach in case of errors or no hardware threads.
230+ if cpus < 1 {
231+ let mut mib = [ libc:: CTL_HW , libc:: HW_NCPU , 0 , 0 ] ;
232+ let res = unsafe {
233+ libc:: sysctl(
234+ mib. as_mut_ptr( ) ,
235+ 2 ,
236+ & mut cpus as * mut _ as * mut _,
237+ & mut cpus_size as * mut _ as * mut _,
238+ ptr:: null_mut( ) ,
239+ 0 ,
240+ )
241+ } ;
242+
243+ // Handle errors if any.
244+ if res == -1 {
245+ return Err ( io:: Error :: last_os_error( ) ) ;
246+ } else if cpus == 0 {
247+ return Err ( io:: Error :: new_const( io:: ErrorKind :: NotFound , & "The number of hardware threads is not known for the target platform" ) ) ;
248+ }
249+ }
250+ Ok ( unsafe { NonZeroUsize :: new_unchecked( cpus as usize ) } )
251+ } else if #[ cfg( target_os = "openbsd" ) ] {
252+ use crate :: ptr;
253+
254+ let mut cpus: libc:: c_uint = 0 ;
255+ let mut cpus_size = crate :: mem:: size_of_val( & cpus) ;
256+ let mut mib = [ libc:: CTL_HW , libc:: HW_NCPU , 0 , 0 ] ;
257+
258+ let res = unsafe {
259+ libc:: sysctl(
260+ mib. as_mut_ptr( ) ,
261+ 2 ,
262+ & mut cpus as * mut _ as * mut _,
263+ & mut cpus_size as * mut _ as * mut _,
264+ ptr:: null_mut( ) ,
265+ 0 ,
266+ )
267+ } ;
268+
269+ // Handle errors if any.
270+ if res == -1 {
271+ return Err ( io:: Error :: last_os_error( ) ) ;
272+ } else if cpus == 0 {
273+ return Err ( io:: Error :: new_const( io:: ErrorKind :: NotFound , & "The number of hardware threads is not known for the target platform" ) ) ;
274+ }
275+
276+ Ok ( unsafe { NonZeroUsize :: new_unchecked( cpus as usize ) } )
277+ } else {
278+ // FIXME: implement on vxWorks, Redox, Haiku, l4re
279+ Err ( io:: Error :: new_const( io:: ErrorKind :: NotFound , & "The number of hardware threads is not known for the target platform" ) )
280+ }
281+ }
282+ }
283+
201284#[ cfg( all(
202285 not( target_os = "linux" ) ,
203286 not( target_os = "freebsd" ) ,
0 commit comments