Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/bump_arena_lazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ use crate::{UninitAllocator, sys};
pub struct BumpArenaLazy {
base: NonNull<u8>,
capacity: usize,
// pays the cost of syscall upfront.
page_size: usize,
offset: Cell<usize>,
commit: Cell<usize>,
last_os_error: Cell<i32>,
Expand Down Expand Up @@ -96,11 +98,14 @@ impl BumpArenaLazy {
///
/// [`new`]: BumpArenaLazy::new
pub fn try_new(capacity: usize) -> Result<Self, i32> {
let page_size = sys::page_size();

// saves us one unnecessary syscall.
if capacity == 0 {
return Ok(Self {
base: NonNull::dangling(),
capacity: 0,
page_size,
offset: Cell::new(0),
commit: Cell::new(0),
last_os_error: Cell::new(0),
Expand All @@ -113,6 +118,7 @@ impl BumpArenaLazy {
Ok(Self {
base,
capacity,
page_size,
offset: Cell::new(0),
commit: Cell::new(0),
last_os_error: Cell::new(0),
Expand Down Expand Up @@ -210,11 +216,10 @@ impl BumpArenaLazy {
offset: usize,
size: usize,
) -> Option<&mut [MaybeUninit<u8>]> {
let page = sys::page_size();
let current = self.commit.get();

// Round offset up to the next page boundary, capped by capacity.
let needed = offset.checked_next_multiple_of(page)?.min(self.capacity);
let needed = offset.checked_next_multiple_of(self.page_size)?.min(self.capacity);

// Safety:
// > `current` is page‑aligned and within the reservation.
Expand Down
40 changes: 4 additions & 36 deletions src/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ pub fn page_size() -> usize {
mod platform {
use core::ffi::c_void;
use core::ptr::NonNull;
use core::sync::atomic::{AtomicUsize, Ordering};

unsafe extern "C" {
fn mmap(
Expand Down Expand Up @@ -162,36 +161,18 @@ mod platform {
unsafe { *errno_location() }
}

static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);

#[allow(clippy::cast_sign_loss)]
#[inline]
pub fn page_size() -> usize {
let sz = PAGE_SIZE.load(Ordering::Relaxed);
if sz != 0 {
return sz;
}
page_size_store()
}

#[allow(
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
reason = "getpagesize returns an int, but page sizes are never negative or very large"
)]
#[cold]
fn page_size_store() -> usize {
let raw = unsafe { getpagesize() };
let sz = if raw <= 0 { 4 * 1024 } else { raw as usize };
PAGE_SIZE.store(sz, Ordering::Relaxed);
sz
let sz = unsafe { getpagesize() };
if sz <= 0 { 4 * 1024 } else { sz as usize }
}
}

#[cfg(target_os = "windows")]
mod platform {
use core::ffi::c_void;
use core::ptr::NonNull;
use core::sync::atomic::{AtomicUsize, Ordering};

unsafe extern "system" {
fn VirtualAlloc(
Expand Down Expand Up @@ -248,23 +229,10 @@ mod platform {
unsafe { GetLastError() }.cast_signed()
}

static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);

#[inline]
pub fn page_size() -> usize {
let sz = PAGE_SIZE.load(Ordering::Relaxed);
if sz != 0 {
return sz;
}
page_size_store()
}

#[cold]
fn page_size_store() -> usize {
let mut info: SYSTEM_INFO = unsafe { core::mem::zeroed() };
unsafe { GetSystemInfo(&raw mut info) };
let sz = info.dwPageSize as usize;
PAGE_SIZE.store(sz, Ordering::Relaxed);
sz
info.dwPageSize as usize
}
}
9 changes: 7 additions & 2 deletions src/typed_arena_lazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ use crate::sys;
pub struct TypedArenaLazy<T> {
base: NonNull<MaybeUninit<T>>,
capacity: usize,
// pays the cost of syscall upfront.
page_size: usize,
offset: Cell<usize>,
commit: Cell<usize>,
last_os_error: Cell<i32>,
Expand Down Expand Up @@ -76,10 +78,13 @@ impl<T> TypedArenaLazy<T> {
///
/// [`new`]: TypedArenaLazy::new
pub fn try_new(capacity: usize) -> Result<Self, i32> {
let page_size = sys::page_size();

if capacity == 0 || size_of::<T>() == 0 {
return Ok(Self {
base: NonNull::dangling(),
capacity,
page_size,
offset: Cell::new(0),
commit: Cell::new(0),
last_os_error: Cell::new(0),
Expand All @@ -94,6 +99,7 @@ impl<T> TypedArenaLazy<T> {
Ok(Self {
base: base.cast(),
capacity,
page_size,
offset: Cell::new(0),
commit: Cell::new(0),
last_os_error: Cell::new(0),
Expand Down Expand Up @@ -181,14 +187,13 @@ impl<T> TypedArenaLazy<T> {
#[inline(never)]
#[allow(clippy::mut_from_ref)]
fn alloc_bump(&self, idx: usize, required_bytes: usize, value: T) -> Option<&mut T> {
let page = sys::page_size();
let current = self.commit.get();

// `new` guarantees `capacity * size_of::<T>()` fits.
let total_bytes = self.capacity * size_of::<T>();

// Next page rounding
let needed = required_bytes.checked_next_multiple_of(page)?.min(total_bytes);
let needed = required_bytes.checked_next_multiple_of(self.page_size)?.min(total_bytes);

// Safety:
// > `current` is page‑aligned and within the reservation.
Expand Down
Loading