Skip to main content

mnemosyne_core/
options.rs

1//! Global thread-safe runtime configuration options.
2//!
3//! These options are populated once at startup from environment variables
4//! and accessed via relaxed atomic reads throughout the allocator.
5
6use core::sync::atomic::{AtomicBool, AtomicUsize};
7
8/// The maximum number of segments retained in the global segment pool.
9pub static MAX_RETAINED_SEGMENTS: AtomicUsize = AtomicUsize::new(default_max_retained_segments());
10
11const fn default_max_retained_segments() -> usize {
12    // Miri reports intentionally retained process-global cache mappings as
13    // leaks. Zero retention keeps Miri's ownership/leak evidence focused on
14    // live allocations while leaving production's bounded cache unchanged.
15    if cfg!(miri) {
16        0
17    } else {
18        crate::constants::MAX_RETAINED_SEGMENTS_LIMIT
19    }
20}
21
22/// Whether the advisory huge page hint (`MADV_HUGEPAGE`) is enabled on Linux.
23pub static ENABLE_HUGEPAGE_HINT: AtomicBool = AtomicBool::new(true);
24
25/// The cadence in milliseconds at which retained segments are purged in the background.
26pub static PURGE_CADENCE_MS: AtomicUsize = AtomicUsize::new(0);
27
28/// Runtime configuration options for the Mnemosyne allocator.
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
30pub struct MnemosyneOptions {
31    /// Free segments the pool keeps for reuse before purging the rest back to
32    /// the OS; clamped at set time to `MAX_RETAINED_SEGMENTS_LIMIT`.
33    pub max_retained_segments: usize,
34    /// Background purge cadence in milliseconds; zero disables background
35    /// decay entirely, leaving purges to the allocation path.
36    pub purge_cadence_ms: usize,
37    /// Whether segment mappings advise the kernel to back them with huge
38    /// pages (`MADV_HUGEPAGE`); a hint only, honored on Linux.
39    pub enable_hugepage_hint: bool,
40}
41
42impl Default for MnemosyneOptions {
43    #[inline]
44    fn default() -> Self {
45        Self {
46            max_retained_segments: default_max_retained_segments(),
47            purge_cadence_ms: 0,
48            enable_hugepage_hint: true,
49        }
50    }
51}
52
53/// Returns the current runtime configuration options snapshot.
54#[inline]
55pub fn get_options() -> MnemosyneOptions {
56    use core::sync::atomic::Ordering;
57    MnemosyneOptions {
58        max_retained_segments: MAX_RETAINED_SEGMENTS.load(Ordering::Acquire),
59        purge_cadence_ms: PURGE_CADENCE_MS.load(Ordering::Acquire),
60        enable_hugepage_hint: ENABLE_HUGEPAGE_HINT.load(Ordering::Acquire),
61    }
62}
63
64/// Overwrites the runtime configuration options.
65#[inline]
66pub fn set_options(options: MnemosyneOptions) {
67    use core::sync::atomic::Ordering;
68    let clamped_retained = core::cmp::min(
69        options.max_retained_segments,
70        crate::constants::MAX_RETAINED_SEGMENTS_LIMIT,
71    );
72    MAX_RETAINED_SEGMENTS.store(clamped_retained, Ordering::Release);
73    PURGE_CADENCE_MS.store(options.purge_cadence_ms, Ordering::Release);
74    ENABLE_HUGEPAGE_HINT.store(options.enable_hugepage_hint, Ordering::Release);
75}