make check_for and the feature cache function inline

This commit is contained in:
gnzlbg 2018-06-20 15:57:05 +02:00 committed by gnzlbg
parent 784fb26d8c
commit 14a5742d4e
10 changed files with 44 additions and 28 deletions

View file

@ -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
}

View file

@ -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,
{

View file

@ -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| {

View file

@ -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)
}

View file

@ -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:

View file

@ -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) => {

View file

@ -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)
}

View file

@ -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)
}

View file

@ -3,6 +3,7 @@
use arch::detect::Feature;
/// Performs run-time feature detection.
#[inline]
pub fn check_for(_x: Feature) -> bool {
false
}

View file

@ -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