#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::_mm_clflush;
#[link(name = "clf")]
extern "C" {
#[allow(dead_code)]
fn clf_fallback_clear_cache(begin_ptr: *const u8, end_ptr: *const u8);
}
fn get_cache_line_size() -> usize {
use core::sync::atomic::{AtomicUsize, Ordering};
static CACHE_LINE_SIZE: AtomicUsize = AtomicUsize::new(0);
let size = CACHE_LINE_SIZE.load(Ordering::Relaxed);
if size != 0 {
return size;
}
let detected_size = detect_cache_line_size();
CACHE_LINE_SIZE.store(detected_size, Ordering::Relaxed);
detected_size
}
fn detect_cache_line_size() -> usize {
#[cfg(target_arch = "x86_64")]
{
#[allow(unused_unsafe)]
let cpuid = unsafe { core::arch::x86_64::__cpuid(1) };
let size = ((cpuid.ebx >> 8) & 0xff) as usize * 8;
if size != 0 {
return size;
}
}
64
}
pub unsafe fn cache_line_flush_with_ptr(begin_ptr: *const u8, end_ptr: *const u8) {
#[cfg(target_arch = "x86_64")]
{
let size = get_cache_line_size();
let mut ptr = begin_ptr;
while ptr < end_ptr {
_mm_clflush(ptr);
ptr = ptr.add(size);
}
}
#[cfg(target_arch = "aarch64")]
{
let size = get_cache_line_size();
let mut ptr = begin_ptr as usize;
let end = end_ptr as usize;
while ptr < end {
core::arch::asm!("dc civac, {0}", in(reg) ptr, options(nostack, preserves_flags));
ptr += size;
}
core::arch::asm!("dsb ish", options(nostack, preserves_flags));
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{
clf_fallback_clear_cache(begin_ptr, end_ptr);
}
}
pub fn cache_line_flush_with_slice<T>(slice: &[T]) {
let begin_ptr = slice.as_ptr() as *const u8;
let end_ptr = unsafe { begin_ptr.add(core::mem::size_of_val(slice)) };
unsafe { cache_line_flush_with_ptr(begin_ptr, end_ptr) };
}
#[cfg(test)]
mod tests {
#[test]
fn it_works_1() {
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
unsafe {
super::cache_line_flush_with_ptr(a.as_ptr(), a.as_ptr().add(a.len()));
}
}
#[test]
fn it_works_2() {
let a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
super::cache_line_flush_with_slice(&a);
}
#[test]
fn large_slice() {
let a = vec![0u8; 1024 * 1024]; super::cache_line_flush_with_slice(&a);
}
}