use core::sync::atomic::{AtomicU64, Ordering};
use crate::segment::Segment;
use crate::types::SEGMENT_SIZE;
const ADDR_BITS: usize = 48;
const WINDOW_SHIFT: usize = 25; const MAP_BITS: usize = 1 << (ADDR_BITS - WINDOW_SHIFT);
const MAP_WORDS: usize = MAP_BITS / 64;
const _: () = assert!(1 << WINDOW_SHIFT == SEGMENT_SIZE);
static MAP: [AtomicU64; MAP_WORDS] = [const { AtomicU64::new(0) }; MAP_WORDS];
#[inline]
fn locate(addr: usize) -> Option<(usize, u64)> {
let idx = addr >> WINDOW_SHIFT;
if idx >= MAP_BITS {
return None;
}
Some((idx / 64, 1u64 << (idx % 64)))
}
pub fn register(seg: *mut Segment) {
register_range(seg.addr(), SEGMENT_SIZE);
}
pub fn register_range(base: usize, size: usize) {
let mut a = base;
let end = base + size.max(1);
while a < end {
if let Some((w, bit)) = locate(a) {
MAP[w].fetch_or(bit, Ordering::Release);
}
a += SEGMENT_SIZE;
}
}
pub fn unregister(seg: *mut Segment) {
unregister_range(seg.addr(), SEGMENT_SIZE);
}
pub fn unregister_range(base: usize, size: usize) {
let mut a = base;
let end = base + size.max(1);
while a < end {
if let Some((w, bit)) = locate(a) {
MAP[w].fetch_and(!bit, Ordering::Release);
}
a += SEGMENT_SIZE;
}
}
pub fn contains(p: *const u8) -> bool {
match locate(p.addr()) {
Some((w, bit)) => MAP[w].load(Ordering::Acquire) & bit != 0,
None => false,
}
}