use super::os::Segment;
use super::segment_header::{Layout, SegmentHeader, SegmentKind, SegmentMeta};
use super::segment_table::{self, SegmentTable};
pub(crate) struct Primordial {
pub segment: Segment,
pub table: SegmentTable,
}
pub(crate) fn primordial() -> Option<Primordial> {
let segment = Segment::reserve(super::os::SEGMENT)?;
let base = segment.as_ptr();
let reservation = segment.reservation();
let reservation_len = segment.reservation_len();
let mut meta = SegmentMeta::new(base);
meta.write_header(SegmentHeader::small(
0,
0,
reservation.as_ptr(),
reservation_len,
));
let pm_off = Layout::page_map_off();
let bt_off = Layout::bin_table_off();
let reg_off = Layout::primordial_registry_off();
let meta_end = Layout::primordial_meta_end();
let meta_pages = Layout::primordial_meta_pages();
super::segment_header::PageMap::init_in_place(base_plus(base, pm_off), meta_pages);
super::segment_header::BinTable::init_in_place(base_plus(base, bt_off) as *mut u32);
super::alloc_bitmap::AllocBitmap::init_in_place(base_plus(base, Layout::alloc_bitmap_off()));
#[cfg(feature = "alloc-xthread")]
{
let ring_off = Layout::remote_ring_off();
super::remote_free_ring::RemoteFreeRing::init_in_place(base, ring_off);
}
let reg_slots = base_plus(base, reg_off) as *mut *mut u8;
super::node::Node::write_struct::<*mut u8>(reg_slots, base);
let hash_off = Layout::primordial_hash_off();
let hash_slots = base_plus(base, hash_off) as *mut *mut u8;
for i in 0..segment_table::HASH_CAPACITY {
let slot =
super::node::Node::offset(hash_slots as *mut u8, i * core::mem::size_of::<*mut u8>())
as *mut *mut u8;
super::node::Node::write_struct::<*mut u8>(slot, core::ptr::null_mut());
}
{
let start_idx =
(base as usize >> segment_table::SEGMENT_SHIFT) & (segment_table::HASH_CAPACITY - 1);
let hash_slot = super::node::Node::offset(
hash_slots as *mut u8,
start_idx * core::mem::size_of::<*mut u8>(),
) as *mut *mut u8;
super::node::Node::write_struct::<*mut u8>(hash_slot, base);
}
let mut hdr = meta.header();
hdr.kind = SegmentKind::Primordial;
hdr.bump = meta_end;
meta.write_header(hdr);
let table = SegmentTable::from_primordial(reg_slots, 1, hash_slots);
Some(Primordial { segment, table })
}
fn base_plus(base: *mut u8, off: usize) -> *mut u8 {
super::node::Node::offset(base, off)
}