extern crate std;
use super::*;
use crate::recorders::backend_memory_stats;
use mnemosyne_core::MemoryBackend;
static HINT_COUNTER_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
fn hugepage_hints() -> usize {
backend_memory_stats().hugepage_hint_calls
}
#[cfg(not(miri))]
#[test]
fn segment_sized_allocation_survives_hugepage_hint() {
let _guard = HINT_COUNTER_LOCK
.lock()
.expect("hugepage hint counter lock was poisoned");
let size = SEGMENT_SIZE;
let before = hugepage_hints();
let ptr = unsafe { UnixBackend::allocate(size) };
assert!(!ptr.is_null(), "segment-sized mapping must succeed");
assert_eq!(
hugepage_hints(),
before + 1,
"a mapping of exactly SEGMENT_SIZE must receive the hugepage hint"
);
unsafe {
ptr.write_volatile(0xAA);
ptr.add(size - 1).write_volatile(0x55);
assert_eq!(ptr.read_volatile(), 0xAA);
assert_eq!(ptr.add(size - 1).read_volatile(), 0x55);
}
let released = unsafe { UnixBackend::deallocate(ptr, size) };
assert!(
released,
"munmap reported failure for segment-sized mapping"
);
}
#[cfg(not(miri))]
#[test]
fn sub_segment_allocation_skips_hugepage_hint() {
let _guard = HINT_COUNTER_LOCK
.lock()
.expect("hugepage hint counter lock was poisoned");
let size = PAGE_SIZE_FALLBACK;
let before = hugepage_hints();
let ptr = unsafe { UnixBackend::allocate(size) };
assert!(!ptr.is_null());
assert_eq!(
hugepage_hints(),
before,
"a sub-SEGMENT_SIZE mapping must not receive the hugepage hint"
);
unsafe {
ptr.write_volatile(0xAA);
ptr.add(size - 1).write_volatile(0x55);
}
let released = unsafe { UnixBackend::deallocate(ptr, size) };
assert!(released);
}
#[cfg(not(miri))]
#[test]
fn large_non_multiple_allocation_receives_hugepage_hint() {
let _guard = HINT_COUNTER_LOCK
.lock()
.expect("hugepage hint counter lock was poisoned");
let size = 3 * 1024 * 1024;
let before = hugepage_hints();
let ptr = unsafe { UnixBackend::allocate(size) };
assert!(!ptr.is_null(), "large mapping must succeed");
assert_eq!(
hugepage_hints(),
before + 1,
"a mapping above SEGMENT_SIZE must receive the hugepage hint even \
when it is not a whole multiple of it"
);
unsafe {
ptr.write_volatile(0xAA);
ptr.add(size - 1).write_volatile(0x55);
assert_eq!(ptr.read_volatile(), 0xAA);
assert_eq!(ptr.add(size - 1).read_volatile(), 0x55);
}
let released = unsafe { UnixBackend::deallocate(ptr, size) };
assert!(
released,
"munmap reported failure for large non-multiple mapping"
);
}
const PAGE_SIZE_FALLBACK: usize = 4096;