standback 0.4.3

New standard library, old compiler.
Documentation
use core::num::NonZeroUsize;
use std::io;

#[cfg(windows)]
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
    use core::ffi::c_void;
    use std::os::raw::c_ulong;

    #[link(name = "kernel32")]
    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    #[repr(C)]
    #[allow(non_snake_case)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: c_ulong,
        lpMinimumApplicationAddress: *mut c_void,
        lpMaximumApplicationAddress: *mut c_void,
        dwActiveProcessorMask: usize,
        dwNumberOfProcessors: c_ulong,
        dwProcessorType: c_ulong,
        dwAllocationGranularity: c_ulong,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    let res = unsafe {
        let mut sysinfo: SYSTEM_INFO = core::mem::zeroed();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    };
    match res {
        0 => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "The number of hardware threads is not known for the target platform",
        )),
        cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }),
    }
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
    use core::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = core::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }

    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,
            )
        };

        if res == -1 {
            return Err(io::Error::last_os_error());
        } else if cpus == 0 {
            return Err(io::Error::new(
                io::ErrorKind::NotFound,
                "The number of hardware threads is not known for the target platform",
            ));
        }
    }
    Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
}

#[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",
))]
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
    use core::mem;

    #[cfg(any(target_os = "android", target_os = "linux"))]
    {
        let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
        if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
            let count = unsafe { libc::CPU_COUNT(&set) };
            return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
        }
    }
    match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
        -1 => Err(io::Error::last_os_error()),
        0 => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "The number of hardware threads is not known for the target platform",
        )),
        cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }),
    }
}

#[cfg(target_os = "openbsd")]
pub fn available_parallelism() -> 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,
        )
    };

    if res == -1 {
        Err(io::Error::last_os_error())
    } else if cpus == 0 {
        Err(io::Error::new(
            io::ErrorKind::NotFound,
            "The number of hardware threads is not known for the target platform",
        ))
    } else {
        Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
    }
}

#[cfg(target_os = "haiku")]
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
    unsafe {
        let mut sinfo: libc::system_info = crate::mem::zeroed();
        let res = libc::get_system_info(&mut sinfo);

        if res != libc::B_OK {
            return Err(io::Error::new(
                io::ErrorKind::NotFound,
                "The number of hardware threads is not known for the target platform",
            ));
        }

        Ok(NonZeroUsize::new_unchecked(sinfo.cpu_count as usize))
    }
}

#[cfg(not(any(
    windows,
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "android",
    target_os = "emscripten",
    target_os = "fuchsia",
    target_os = "ios",
    target_os = "linux",
    target_os = "macos",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "openbsd",
    target_os = "haiku",
)))]
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
    Err(io::Error::new(
        io::ErrorKind::Unsupported,
        "Getting the number of hardware threads is not supported on the target platform",
    ))
}