make check_for and the feature cache function inline
This commit is contained in:
parent
784fb26d8c
commit
14a5742d4e
10 changed files with 44 additions and 28 deletions
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
/// Tests the `bit` of `x`.
|
||||
#[allow(dead_code)]
|
||||
pub fn test(x: usize, bit: u32) -> bool {
|
||||
#[inline]
|
||||
pub(crate) fn test(x: usize, bit: u32) -> bool {
|
||||
debug_assert!(bit < 32, "bit index out-of-bounds");
|
||||
x & (1 << bit) != 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,14 @@ use core::sync::atomic::AtomicU64;
|
|||
use core::sync::atomic::AtomicU32;
|
||||
|
||||
/// Sets the `bit` of `x`.
|
||||
pub const fn set_bit(x: u64, bit: u32) -> u64 {
|
||||
#[inline]
|
||||
const fn set_bit(x: u64, bit: u32) -> u64 {
|
||||
x | 1 << bit
|
||||
}
|
||||
|
||||
/// Tests the `bit` of `x`.
|
||||
pub const fn test_bit(x: u64, bit: u32) -> bool {
|
||||
#[inline]
|
||||
const fn test_bit(x: u64, bit: u32) -> bool {
|
||||
x & (1 << bit) != 0
|
||||
}
|
||||
|
||||
|
|
@ -26,7 +28,7 @@ const CACHE_CAPACITY: u32 = 63;
|
|||
|
||||
/// This type is used to initialize the cache
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Initializer(u64);
|
||||
pub(crate) struct Initializer(u64);
|
||||
|
||||
impl Default for Initializer {
|
||||
fn default() -> Self {
|
||||
|
|
@ -37,7 +39,8 @@ impl Default for Initializer {
|
|||
impl Initializer {
|
||||
/// Tests the `bit` of the cache.
|
||||
#[allow(dead_code)]
|
||||
pub fn test(&self, bit: u32) -> bool {
|
||||
#[inline]
|
||||
pub(crate) fn test(&self, bit: u32) -> bool {
|
||||
// FIXME: this way of making sure that the cache is large enough is
|
||||
// brittle.
|
||||
debug_assert!(
|
||||
|
|
@ -48,7 +51,8 @@ impl Initializer {
|
|||
}
|
||||
|
||||
/// Sets the `bit` of the cache.
|
||||
pub fn set(&mut self, bit: u32) {
|
||||
#[inline]
|
||||
pub(crate) fn set(&mut self, bit: u32) {
|
||||
// FIXME: this way of making sure that the cache is large enough is
|
||||
// brittle.
|
||||
debug_assert!(
|
||||
|
|
@ -77,17 +81,20 @@ impl Cache {
|
|||
Cache(AtomicU64::new(u64::max_value()))
|
||||
}
|
||||
/// Is the cache uninitialized?
|
||||
pub fn is_uninitialized(&self) -> bool {
|
||||
#[inline]
|
||||
pub(crate) fn is_uninitialized(&self) -> bool {
|
||||
self.0.load(Ordering::Relaxed) == u64::max_value()
|
||||
}
|
||||
|
||||
/// Is the `bit` in the cache set?
|
||||
pub fn test(&self, bit: u32) -> bool {
|
||||
#[inline]
|
||||
pub(crate) fn test(&self, bit: u32) -> bool {
|
||||
test_bit(CACHE.0.load(Ordering::Relaxed), bit)
|
||||
}
|
||||
|
||||
/// Initializes the cache.
|
||||
pub fn initialize(&self, value: Initializer) {
|
||||
#[inline]
|
||||
pub(crate) fn initialize(&self, value: Initializer) {
|
||||
self.0.store(value.0, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
|
@ -109,12 +116,14 @@ impl Cache {
|
|||
)
|
||||
}
|
||||
/// Is the cache uninitialized?
|
||||
pub fn is_uninitialized(&self) -> bool {
|
||||
#[inline]
|
||||
pub(crate) fn is_uninitialized(&self) -> bool {
|
||||
self.1.load(Ordering::Relaxed) == u32::max_value()
|
||||
}
|
||||
|
||||
/// Is the `bit` in the cache set?
|
||||
pub fn test(&self, bit: u32) -> bool {
|
||||
#[inline]
|
||||
pub(crate) fn test(&self, bit: u32) -> bool {
|
||||
if bit < 32 {
|
||||
test_bit(CACHE.0.load(Ordering::Relaxed) as u64, bit)
|
||||
} else {
|
||||
|
|
@ -123,7 +132,8 @@ impl Cache {
|
|||
}
|
||||
|
||||
/// Initializes the cache.
|
||||
pub fn initialize(&self, value: Initializer) {
|
||||
#[inline]
|
||||
pub(crate) fn initialize(&self, value: Initializer) {
|
||||
let lo: u32 = value.0 as u32;
|
||||
let hi: u32 = (value.0 >> 32) as u32;
|
||||
self.0.store(lo, Ordering::Relaxed);
|
||||
|
|
@ -139,9 +149,8 @@ impl Cache {
|
|||
///
|
||||
/// It uses the `Feature` variant to index into this variable as a bitset. If
|
||||
/// the bit is set, the feature is enabled, and otherwise it is disabled.
|
||||
///
|
||||
/// PLEASE: do not use this, it is an implementation detail subject to change.
|
||||
pub fn test<F>(bit: u32, f: F) -> bool
|
||||
#[inline]
|
||||
pub(crate) fn test<F>(bit: u32, f: F) -> bool
|
||||
where
|
||||
F: FnOnce() -> Initializer,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use super::auxvec;
|
|||
use super::cpuinfo;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
#[inline]
|
||||
pub fn check_for(x: Feature) -> bool {
|
||||
cache::test(x as u32, detect_features)
|
||||
}
|
||||
|
|
@ -125,7 +126,7 @@ impl AtHwcap {
|
|||
///
|
||||
/// The features are enabled approximately like in LLVM host feature detection:
|
||||
/// https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Host.cpp#L1273
|
||||
pub fn cache(self) -> cache::Initializer {
|
||||
fn cache(self) -> cache::Initializer {
|
||||
let mut value = cache::Initializer::default();
|
||||
{
|
||||
let mut enable_feature = |f, enable| {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use super::auxvec;
|
|||
use super::cpuinfo;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
#[inline]
|
||||
pub fn check_for(x: Feature) -> bool {
|
||||
cache::test(x as u32, detect_features)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ use fs::File;
|
|||
use io::Read;
|
||||
|
||||
/// Key to access the CPU Hardware capabilities bitfield.
|
||||
pub const AT_HWCAP: usize = 16;
|
||||
pub(crate) const AT_HWCAP: usize = 16;
|
||||
/// Key to access the CPU Hardware capabilities 2 bitfield.
|
||||
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
|
||||
pub const AT_HWCAP2: usize = 26;
|
||||
pub(crate) const AT_HWCAP2: usize = 26;
|
||||
|
||||
/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
|
||||
///
|
||||
/// If an entry cannot be read all the bits in the bitfield are set to zero.
|
||||
/// This should be interpreted as all the features being disabled.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct AuxVec {
|
||||
pub(crate) struct AuxVec {
|
||||
pub hwcap: usize,
|
||||
#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))]
|
||||
pub hwcap2: usize,
|
||||
|
|
@ -48,7 +48,7 @@ pub struct AuxVec {
|
|||
///
|
||||
/// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h
|
||||
/// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/
|
||||
pub fn auxv() -> Result<AuxVec, ()> {
|
||||
pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
||||
// Try to call a dynamically-linked getauxval function.
|
||||
if let Ok(hwcap) = getauxval(AT_HWCAP) {
|
||||
// Targets with only AT_HWCAP:
|
||||
|
|
|
|||
|
|
@ -6,20 +6,20 @@ use fs::File;
|
|||
use io::{self, Read};
|
||||
|
||||
/// cpuinfo
|
||||
pub struct CpuInfo {
|
||||
pub(crate) struct CpuInfo {
|
||||
raw: String,
|
||||
}
|
||||
|
||||
impl CpuInfo {
|
||||
/// Reads /proc/cpuinfo into CpuInfo.
|
||||
pub fn new() -> Result<Self, io::Error> {
|
||||
pub(crate) fn new() -> Result<Self, io::Error> {
|
||||
let mut file = File::open("/proc/cpuinfo")?;
|
||||
let mut cpui = Self { raw: String::new() };
|
||||
file.read_to_string(&mut cpui.raw)?;
|
||||
Ok(cpui)
|
||||
}
|
||||
/// Returns the value of the cpuinfo `field`.
|
||||
pub fn field(&self, field: &str) -> CpuInfoField {
|
||||
pub(crate) fn field(&self, field: &str) -> CpuInfoField {
|
||||
for l in self.raw.lines() {
|
||||
if l.trim().starts_with(field) {
|
||||
return CpuInfoField::new(l.split(": ").nth(1));
|
||||
|
|
@ -44,7 +44,7 @@ impl CpuInfo {
|
|||
|
||||
/// Field of cpuinfo
|
||||
#[derive(Debug)]
|
||||
pub struct CpuInfoField<'a>(Option<&'a str>);
|
||||
pub(crate) struct CpuInfoField<'a>(Option<&'a str>);
|
||||
|
||||
impl<'a> PartialEq<&'a str> for CpuInfoField<'a> {
|
||||
fn eq(&self, other: &&'a str) -> bool {
|
||||
|
|
@ -56,7 +56,7 @@ impl<'a> PartialEq<&'a str> for CpuInfoField<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CpuInfoField<'a> {
|
||||
pub fn new<'b>(v: Option<&'b str>) -> CpuInfoField<'b> {
|
||||
pub(crate) fn new<'b>(v: Option<&'b str>) -> CpuInfoField<'b> {
|
||||
match v {
|
||||
None => CpuInfoField::<'b>(None),
|
||||
Some(f) => CpuInfoField::<'b>(Some(f.trim())),
|
||||
|
|
@ -64,11 +64,11 @@ impl<'a> CpuInfoField<'a> {
|
|||
}
|
||||
/// Does the field exist?
|
||||
#[cfg(test)]
|
||||
pub fn exists(&self) -> bool {
|
||||
pub(crate) fn exists(&self) -> bool {
|
||||
self.0.is_some()
|
||||
}
|
||||
/// Does the field contain `other`?
|
||||
pub fn has(&self, other: &str) -> bool {
|
||||
pub(crate) fn has(&self, other: &str) -> bool {
|
||||
match self.0 {
|
||||
None => other.is_empty(),
|
||||
Some(f) => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use arch::detect::bit;
|
|||
use super::auxvec;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
#[inline]
|
||||
pub fn check_for(x: Feature) -> bool {
|
||||
cache::test(x as u32, detect_features)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use super::auxvec;
|
|||
use super::cpuinfo;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
#[inline]
|
||||
pub fn check_for(x: Feature) -> bool {
|
||||
cache::test(x as u32, detect_features)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use arch::detect::Feature;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
#[inline]
|
||||
pub fn check_for(_x: Feature) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use arch::detect::cache;
|
|||
use arch::detect::bit;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
#[inline]
|
||||
pub fn check_for(x: Feature) -> bool {
|
||||
cache::test(x as u32, detect_features)
|
||||
}
|
||||
|
|
@ -32,7 +33,7 @@ pub fn check_for(x: Feature) -> bool {
|
|||
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
|
||||
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(similar_names))]
|
||||
pub fn detect_features() -> cache::Initializer {
|
||||
fn detect_features() -> cache::Initializer {
|
||||
let mut value = cache::Initializer::default();
|
||||
|
||||
// If the x86 CPU does not support the CPUID instruction then it is too
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue