use core::ptr::NonNull;
use mnemosyne_core::policy::AllocPolicy;
use mnemosyne_core::types::{Block, Page, Segment, try_pop_bump_block};
#[inline(always)]
pub(crate) unsafe fn try_allocate_page_local<P: AllocPolicy>(
page: *mut Page,
) -> Option<NonNull<Block>> {
unsafe {
try_allocate_page_local_dynamic(
page,
P::ENABLE_FREE_LIST_ENCRYPTION,
P::RANDOMIZE_ALLOCATION,
)
}
}
#[inline(always)]
pub(crate) unsafe fn try_allocate_page_local_dynamic(
page: *mut Page,
enable_encryption: bool,
randomize: bool,
) -> Option<NonNull<Block>> {
unsafe {
if (*page).free.is_none()
&& (*page).secondary_free.is_none()
&& (*page).initialized_blocks as usize >= (*page).max_blocks()
{
return None;
}
let block = if let Some(block) = try_pop_bump_block(page) {
block
} else if (*page).free.is_some() || (*page).secondary_free.is_some() {
Page::pop_block_dynamic(page, enable_encryption, randomize)
} else {
return None;
};
if (*page).alloc_count == 0 {
Page::increment_alloc_count(page);
} else {
(*page).alloc_count = ((*page).alloc_count as usize + 1) as u32;
}
Some(block)
}
}
#[inline(always)]
pub(crate) unsafe fn try_reclaim_and_allocate<P: AllocPolicy>(
page: *mut Page,
reclaim_sink: &mut usize,
) -> Option<NonNull<Block>> {
unsafe {
try_reclaim_and_allocate_dynamic(
page,
reclaim_sink,
P::ENABLE_FREE_LIST_ENCRYPTION,
P::RANDOMIZE_ALLOCATION,
)
}
}
#[inline(always)]
pub(crate) unsafe fn try_reclaim_and_allocate_dynamic(
page: *mut Page,
reclaim_sink: &mut usize,
enable_encryption: bool,
randomize: bool,
) -> Option<NonNull<Block>> {
let (segment, page_index) = unsafe {
if (*page).thread_free.is_empty() {
return None;
}
(Page::parent_segment_of(page), (*page).index_in_segment())
};
let encrypted = unsafe { Segment::free_list_encrypted(segment) };
let randomized = randomize && encrypted;
let reclaimed =
unsafe { Page::reclaim_thread_free_in_segment(segment, page_index, encrypted, randomized) };
if reclaimed == 0 {
return None;
}
*reclaim_sink += reclaimed;
let block = unsafe { try_allocate_page_local_dynamic(page, enable_encryption, randomize) }
.expect("invariant: reclaimed remote frees populate the page-local free list");
Some(block)
}