@@ -2,6 +2,7 @@ use crate::cmp;
2
2
use crate :: ffi:: CStr ;
3
3
use crate :: io;
4
4
use crate :: mem;
5
+ use crate :: num:: NonZeroUsize ;
5
6
use crate :: ptr;
6
7
use crate :: sys:: { os, stack_overflow} ;
7
8
use crate :: time:: Duration ;
@@ -198,6 +199,88 @@ impl Drop for Thread {
198
199
}
199
200
}
200
201
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
+
201
284
#[ cfg( all(
202
285
not( target_os = "linux" ) ,
203
286
not( target_os = "freebsd" ) ,
0 commit comments