use core::ffi::c_void;
use std::collections::HashMap;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use super::{Alloc, MemConfig, PrimError, TlsDtor};
const MOCK_PAGE: usize = 4096;
const MERR: PrimError = 0xDEAD;
fn registry() -> &'static Mutex<HashMap<usize, std::alloc::Layout>> {
static REG: std::sync::OnceLock<Mutex<HashMap<usize, std::alloc::Layout>>> =
std::sync::OnceLock::new();
REG.get_or_init(|| Mutex::new(HashMap::new()))
}
pub(super) fn mem_init() -> MemConfig {
MemConfig {
page_size: MOCK_PAGE,
alloc_granularity: MOCK_PAGE,
large_page_size: 0,
has_overcommit: false,
has_partial_free: false,
}
}
pub(super) unsafe fn alloc(
size: usize,
try_alignment: usize,
_commit: bool,
_allow_large: bool,
) -> Result<Alloc, PrimError> {
let align = try_alignment.max(MOCK_PAGE);
let layout = std::alloc::Layout::from_size_align(size, align).map_err(|_| MERR)?;
let p = unsafe { std::alloc::alloc_zeroed(layout) };
if p.is_null() {
return Err(MERR);
}
registry().lock().unwrap().insert(p as usize, layout);
Ok(Alloc {
ptr: p,
is_large: false,
is_zero: true,
})
}
pub(super) unsafe fn free(ptr_: *mut u8, _size: usize) -> Result<(), PrimError> {
let layout = registry()
.lock()
.unwrap()
.remove(&(ptr_ as usize))
.ok_or(MERR)?;
unsafe { std::alloc::dealloc(ptr_, layout) };
Ok(())
}
pub(super) unsafe fn commit(_ptr: *mut u8, _size: usize) -> Result<bool, PrimError> {
Ok(false)
}
pub(super) unsafe fn decommit(_ptr: *mut u8, _size: usize) -> Result<bool, PrimError> {
Ok(false)
}
pub(super) unsafe fn reset(_ptr: *mut u8, _size: usize) -> Result<(), PrimError> {
Ok(())
}
pub(super) unsafe fn protect(_ptr: *mut u8, _size: usize, _on: bool) -> Result<(), PrimError> {
Ok(())
}
pub(super) fn numa_node_count() -> usize {
1
}
pub(super) fn thread_id() -> usize {
static NEXT: AtomicUsize = AtomicUsize::new(1);
std::thread_local! {
static ID: usize = NEXT.fetch_add(1, Ordering::Relaxed);
}
ID.with(|id| *id)
}
pub(super) fn clock_now() -> u64 {
static TICKS: AtomicU64 = AtomicU64::new(0);
TICKS.fetch_add(1, Ordering::Relaxed)
}
pub(super) struct TlsSlotImpl(usize);
pub(super) fn tls_new(_dtor: Option<TlsDtor>) -> Option<TlsSlotImpl> {
static NEXT_SLOT: AtomicUsize = AtomicUsize::new(1);
Some(TlsSlotImpl(NEXT_SLOT.fetch_add(1, Ordering::Relaxed)))
}
std::thread_local! {
static TLS: std::cell::RefCell<HashMap<usize, usize>> =
std::cell::RefCell::new(HashMap::new());
}
pub(super) fn tls_get(slot: &TlsSlotImpl) -> *mut c_void {
TLS.with(|m| *m.borrow().get(&slot.0).unwrap_or(&0)) as *mut c_void
}
pub(super) fn tls_set(slot: &TlsSlotImpl, value: *mut c_void) {
TLS.with(|m| m.borrow_mut().insert(slot.0, value as usize));
}
pub(super) fn tls_raw(slot: &TlsSlotImpl) -> usize {
slot.0
}
pub(super) fn tls_from_raw(raw: usize) -> TlsSlotImpl {
TlsSlotImpl(raw)
}