Skip to main content

mnemosyne_arena/segment/pool/
mod.rs

1//! Global segment caches: per-NUMA-node pools of retained segments and huge
2//! mappings, with cross-node stealing when the local node is empty.
3
4mod cache_aligned;
5pub mod huge_pool;
6pub mod list;
7mod node_huge_bucket;
8mod numa_bucket;
9pub mod segment_pool;
10mod tagged_stack;
11
12pub use huge_pool::GlobalHugePool;
13pub use list::NodeSegmentPool;
14pub use segment_pool::GlobalSegmentPool;
15
16/// Point-in-time snapshot of [`GlobalHugePool`] counters.
17///
18/// All fields are individually relaxed reads; not jointly consistent.
19#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
20pub struct HugePoolStats {
21    /// Huge blocks currently held in the warm cache.
22    pub retained_blocks: usize,
23    /// Total bytes of huge blocks in the warm cache.
24    pub retained_bytes: usize,
25}
26
27/// Point-in-time snapshot of [`GlobalSegmentPool`] telemetry counters.
28///
29/// All fields are individually monotone-non-decreasing relaxed reads;
30/// they are not jointly consistent (no single atomic snapshot).
31///
32/// `#[non_exhaustive]`: this snapshot has gained fields three times
33/// (`reset_segments`/`reset_calls`, `oom_retries`/`oom_retry_successes`) as
34/// telemetry grew, and will again — a growing counter set is exactly the
35/// forward-compatibility case the attribute exists for.
36#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
37#[non_exhaustive]
38pub struct SegmentPoolStats {
39    /// Segments currently held in the warm cache.
40    pub retained: usize,
41    /// Cumulative segments returned to the OS by purge passes.
42    pub purged_segments: usize,
43    /// Cumulative purge-pass invocations.
44    pub purge_calls: usize,
45    /// Cumulative segments whose physical backing was dropped by a page-reset.
46    pub reset_segments: usize,
47    /// Cumulative reset-pass invocations.
48    pub reset_calls: usize,
49    /// Cumulative purge-and-retry attempts after a first OS allocation
50    /// failure (`allocate_segment`'s OOM recovery path).
51    pub oom_retries: usize,
52    /// Cumulative purge-and-retry attempts whose retried allocation
53    /// succeeded, a subset of `oom_retries`.
54    pub oom_retry_successes: usize,
55}
56
57/// Sealed trait module to protect architectural invariants.
58#[doc(hidden)]
59pub mod private {
60    pub trait Sealed {}
61}
62
63/// The trio of global pools owned by a single memory backend.
64///
65/// One `const`-constructible bundle replaces the per-backend triplet of
66/// separate statics: each backend owns exactly one `static BackendPools`,
67/// and [`HasSegmentPool`] exposes its three components through default
68/// accessor methods.
69pub struct BackendPools {
70    segment: GlobalSegmentPool,
71    orphan: GlobalSegmentPool,
72    huge: GlobalHugePool,
73}
74
75impl BackendPools {
76    /// Creates a bundle of three empty pools.
77    ///
78    /// Const-constructible so each backend can declare its pools as a single
79    /// `static`, preserving the distinct-per-backend isolation that separate
80    /// statics previously provided.
81    pub const fn new() -> Self {
82        Self {
83            segment: GlobalSegmentPool::new(),
84            orphan: GlobalSegmentPool::new(),
85            huge: GlobalHugePool::new(),
86        }
87    }
88}
89
90impl Default for BackendPools {
91    #[inline]
92    fn default() -> Self {
93        Self::new()
94    }
95}
96
97/// Implements [`private::Sealed`] and [`HasSegmentPool`] for a backend type,
98/// associating it with a named `static BackendPools` instance.
99///
100/// Each backend requires exactly 5 boilerplate lines; this macro eliminates
101/// the duplication across all 7 backends (35 → 7 lines + this definition).
102macro_rules! impl_has_segment_pool {
103    ($backend:ty, $pools_name:ident) => {
104        static $pools_name: BackendPools = BackendPools::new();
105        impl private::Sealed for $backend {}
106        impl HasSegmentPool for $backend {
107            #[inline(always)]
108            fn pools() -> &'static BackendPools {
109                &$pools_name
110            }
111        }
112    };
113}
114
115/// Trait associating a memory backend with its global pools.
116///
117/// Implementors provide a single [`HasSegmentPool::pools`] accessor returning
118/// their owned [`BackendPools`]; the individual pool accessors are supplied as
119/// default methods delegating to it.
120pub trait HasSegmentPool: mnemosyne_core::MemoryBackend + private::Sealed {
121    /// Returns this backend's pool bundle.
122    fn pools() -> &'static BackendPools;
123
124    /// Returns the global segment pool for this backend.
125    #[inline(always)]
126    fn global_segment_pool() -> &'static GlobalSegmentPool {
127        &Self::pools().segment
128    }
129
130    /// Returns the global orphan pool for this backend.
131    #[inline(always)]
132    fn global_orphan_pool() -> &'static GlobalSegmentPool {
133        &Self::pools().orphan
134    }
135
136    /// Returns the global huge allocation pool for this backend.
137    #[inline(always)]
138    fn global_huge_pool() -> &'static GlobalHugePool {
139        &Self::pools().huge
140    }
141}
142
143impl_has_segment_pool!(mnemosyne_backend::DefaultBackend, DEFAULT_BACKEND_POOLS);
144impl_has_segment_pool!(
145    mnemosyne_backend::MemoryBackendWrapper,
146    WRAPPER_BACKEND_POOLS
147);
148impl_has_segment_pool!(mnemosyne_backend::CudaUnifiedBackend, CUDA_BACKEND_POOLS);
149impl_has_segment_pool!(mnemosyne_backend::CudaDeviceBackend, CUDA_DEVICE_POOLS);
150impl_has_segment_pool!(mnemosyne_backend::CudaHbmBackend, CUDA_HBM_POOLS);
151impl_has_segment_pool!(mnemosyne_backend::CudaGddrBackend, CUDA_GDDR_POOLS);
152impl_has_segment_pool!(
153    mnemosyne_backend::CudaHostPinnedBackend,
154    CUDA_HOST_PINNED_POOLS
155);