use std::{
cell::RefCell,
hint::black_box,
mem::{self},
ptr,
sync::LazyLock,
};
#[cfg(not(miri))]
const CACHE_CLEANER_LEN_BYTES: usize = 128 * 1024 * 1024;
#[cfg(miri)]
const CACHE_CLEANER_LEN_BYTES: usize = 1024;
const CACHE_CLEANER_LEN_U64: usize = CACHE_CLEANER_LEN_BYTES / mem::size_of::<u64>();
static CACHE_CLEANER_SOURCE: LazyLock<Vec<u64>> =
LazyLock::new(|| vec![0x0102030401020304; CACHE_CLEANER_LEN_U64]);
thread_local! {
static CACHE_CLEANER_DESTINATION: RefCell<Vec<u64>> =
RefCell::new(vec![0xFFFFFFFFFFFFFFFF; CACHE_CLEANER_LEN_U64]);
}
pub(crate) fn clean_caches() {
let source_ptr = CACHE_CLEANER_SOURCE.as_ptr();
let destination_ptr =
CACHE_CLEANER_DESTINATION.with_borrow_mut(|destination| destination.as_mut_ptr());
unsafe {
ptr::copy_nonoverlapping(source_ptr, destination_ptr, CACHE_CLEANER_LEN_U64);
}
CACHE_CLEANER_DESTINATION.with_borrow_mut(|destination| unsafe {
destination.set_len(CACHE_CLEANER_LEN_U64);
});
let _ = black_box(unsafe { destination_ptr.read() });
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn clean_caches_smoke_test() {
clean_caches();
}
}