Skip to main content

page_size

Function page_size 

Source
pub fn page_size() -> usize
Expand description

Return the OS page size in bytes, querying the OS once and caching the result.

Uses sysconf(_SC_PAGESIZE) on Unix and GetSystemInfo on Windows; under miri it returns PAGE (4 KiB) by design (there is no real OS page). The value is cached in a process-wide atomic after the first call, so repeated calls are a single relaxed load. The returned value is always a power of two and at least PAGE.

Correctness: on Apple Silicon macOS the page size is 16 KiB, and on some Linux configurations 64 KiB. Use this value (not PAGE) to round decommit offsets: decommit/decommit_lazy validate BOTH endpoints against page_size() before reaching the OS, and a misaligned endpoint is a crate-level fail-closed skip (the call returns without any effect). That crate-level validation is the load-bearing guard — do not rely on the OS to reject a misaligned range for you. The kernels’ own behavior is asymmetric and platform-divergent: Linux madvise(2) rejects the call only when the ADDRESS is misaligned, and rounds a misaligned LENGTH up to the real page (touching memory past the requested range); Windows VirtualFree(MEM_DECOMMIT) rejects nothing and widens the range in BOTH directions (it decommits every page containing any byte of the range).

If the one-time OS query fails (sysconf returning an error, or a nonsensical answer — not observed on any supported platform: on Linux/macOS/Windows the page size comes from process-startup data that cannot fail to exist), this function still returns MIN_PAGE (= PAGE, 4 KiB) so it stays infallible — but the crate records the failure and every page-granular STATE operation fails closed for the process lifetime: decommit/decommit_lazy become no-ops, recommit/commit_range return false, the try_* forms and the lazy reservation constructor report an OS-side no-code error (see VmemError::os_refusal_unknown_code), and try_page_size returns Err. Reserving, using, and releasing memory are unaffected — they never depend on the runtime page size. Rationale: with the real page size unknown, a decommit granularity guess could make the OS round a length up across live data; refusing to decommit loses nothing but an optimization, while guessing risks silent data loss.

One bookkeeping value keeps moving even in the degraded state (task #1156, finding F15): LazyReservation::shrink_committed (feature lazy-commit; not an intra-doc link here — page_size is compiled unconditionally and LazyReservation is not, so a real link would break whenever lazy-commit is off, e.g. under plain --no-default-features) lowers its own watermark unconditionally, even though the decommit call it issues underneath is the no-op described above. The watermark is rounded UP using the conservative PAGE value this degraded state substitutes for the unknown real page size, so the dropped range can be smaller than a true page on a host with a larger real page — but shrink_committed documents the watermark as this crate’s own bookkeeping guarantee, “not a claim about residency”, so a lowered watermark under poison is consistent with that contract, not a violation of it: no committed byte the caller is entitled to is released (the underlying decommit did nothing), only the handle’s own record of what it considers committed moves. No other primitive’s return value (bool, Result) is affected by this — shrink_committed is the one entry point in this enumeration with no fallible/boolean signature to report the degraded state through, because it never had one even outside the degraded state.