#[cfg(target_arch = "x86_64")]
use std::sync::OnceLock;
#[cfg(target_arch = "x86_64")]
pub fn has_waitpkg() -> bool {
*waitpkg_available()
}
#[cfg(not(target_arch = "x86_64"))]
pub fn has_waitpkg() -> bool {
false
}
#[cfg(target_arch = "x86_64")]
fn waitpkg_available() -> &'static bool {
static CACHE: OnceLock<bool> = OnceLock::new();
CACHE.get_or_init(|| {
use std::arch::x86_64::{__cpuid, __cpuid_count};
let max_leaf = __cpuid(0).eax;
if max_leaf < 7 {
return false;
}
let r = __cpuid_count(7, 0);
(r.ecx >> 5) & 1 == 1
})
}
#[cfg(target_arch = "x86_64")]
pub fn has_movdir64b() -> bool {
*movdir64b_available()
}
#[cfg(not(target_arch = "x86_64"))]
pub fn has_movdir64b() -> bool {
false
}
#[cfg(target_arch = "x86_64")]
fn movdir64b_available() -> &'static bool {
static CACHE: OnceLock<bool> = OnceLock::new();
CACHE.get_or_init(|| {
use std::arch::x86_64::{__cpuid, __cpuid_count};
let max_leaf = __cpuid(0).eax;
if max_leaf < 7 {
return false;
}
let r = __cpuid_count(7, 0);
(r.ecx >> 28) & 1 == 1
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn has_waitpkg_does_not_panic_and_caches() {
let first = has_waitpkg();
let second = has_waitpkg();
assert_eq!(first, second, "has_waitpkg must be idempotent");
}
#[test]
fn has_movdir64b_does_not_panic_and_caches() {
let first = has_movdir64b();
let second = has_movdir64b();
assert_eq!(first, second, "has_movdir64b must be idempotent");
}
}