Skip to content

Commit 31cfa4a

Browse files
committed
Fall back to _SC_NPROCESSORS_ONLN if sched_getaffinity returns an empty mask
1 parent a6d8724 commit 31cfa4a

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

library/std/src/sys/unix/thread.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -316,25 +316,38 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
316316
target_os = "solaris",
317317
target_os = "illumos",
318318
))] {
319+
#[allow(unused_assignments)]
320+
#[allow(unused_mut)]
321+
let mut quota = usize::MAX;
322+
319323
#[cfg(any(target_os = "android", target_os = "linux"))]
320324
{
321-
let quota = cgroups::quota().max(1);
325+
quota = cgroups::quota().max(1);
322326
let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
323327
unsafe {
324328
if libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) == 0 {
325329
let count = libc::CPU_COUNT(&set) as usize;
326330
let count = count.min(quota);
327-
// reported to occur on MIPS kernels older than our minimum supported kernel version for those targets
328-
let count = NonZeroUsize::new(count)
329-
.expect("CPU count must be > 0. This may be a bug in sched_getaffinity(); try upgrading the kernel.");
330-
return Ok(count);
331+
332+
// According to sched_getaffinity's API it should always be non-zero, but
333+
// some old MIPS kernels were buggy and zero-initialized the mask if
334+
// none was explicitly set.
335+
// In that case we use the sysconf fallback.
336+
if let Some(count) = NonZeroUsize::new(count) {
337+
return Ok(count)
338+
}
331339
}
332340
}
333341
}
334342
match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
335343
-1 => Err(io::Error::last_os_error()),
336344
0 => Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")),
337-
cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }),
345+
cpus => {
346+
let count = cpus as usize;
347+
// Cover the unusual situation where we were able to get the quota but not the affinity mask
348+
let count = count.min(quota);
349+
Ok(unsafe { NonZeroUsize::new_unchecked(count) })
350+
}
338351
}
339352
} else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] {
340353
use crate::ptr;

0 commit comments

Comments
 (0)