pub struct PageSize(/* private fields */);Expand description
A power-of-two page size, stored as a bit-shift (log2 of bytes).
§Safety invariant
The inner value must be a valid page size for the target architecture.
Implementations§
Source§impl PageSize
impl PageSize
Sourcepub const fn from_log2(shift: u8) -> Self
pub const fn from_log2(shift: u8) -> Self
Construct a PageSize from a log2 value. Panics if shift is 0 or >= usize::BITS.
Sourcepub const fn bytes(&self) -> usize
pub const fn bytes(&self) -> usize
The size in bytes.
Examples found in repository?
examples/basic.rs (line 81)
81const MAX_BLOCK: usize = BASE.bytes() << (ORDERS - 1);
82
83/// Total span the allocator manages, in base frames. 256 × 4 KiB = 1 MiB.
84const SPAN_FRAMES: usize = 256;
85
86/// A `const`-constructed `static`: no runtime initialiser, nothing on the heap.
87/// `init` happens once at boot; from then on it is shared, lock-free for the
88/// fast path, across every CPU.
89static PHYS: SummaryBuddyAllocator<ORDERS, IdentityProv> = SummaryBuddyAllocator::new(BASE);
90
91fn main() {
92 // A boot memory map with holes:
93 //
94 // The backing pool spans the whole window; we then declare only the *usable*
95 // sub-ranges. Two holes stay reserved and are never handed out:
96 //
97 // [ 0 .. 100) usable <- the buddy carves its in-pool bitmap from here
98 // [100 .. 104) RESERVED (kernel image)
99 // [104 .. 200) usable
100 // [200 .. 205) RESERVED (MMIO window)
101 // [205 .. 256) usable
102 let pool = Region::new(SPAN_FRAMES * BASE.bytes(), MAX_BLOCK);
103 let phys_base = pool.addr(); // the "physical" origin
104
105 let frame = BASE.bytes();
106 let range = |lo: usize, hi: usize| PhysRange {
107 base: phys_base + lo * frame,
108 len: (hi - lo) * frame,
109 };
110 let usable = [range(0, 100), range(104, 200), range(205, 256)];
111
112 // SAFETY: single-threaded, called once before any allocation. `phys_base` is
113 // MAX_BLOCK-aligned (Region honours the requested alignment); the bitmap host
114 // range is exclusively owned and reachable through `IdentityProv::create`; the
115 // usable ranges are sorted, non-overlapping, base-frame-aligned, and within
116 // the span.
117 unsafe { PHYS.init(phys_base, SPAN_FRAMES * frame, &usable) };
118
119 println!("Initialised SummaryBuddy over a 1 MiB span with two reserved holes.");
120 print_stats("after init", &PHYS);
121
122 // A few allocate / deallocate cycles:
123 //
124 // One single base frame, then a 4-frame (order-2) contiguous block. Every
125 // address is physical and aligned to the request size.
126 let single = PHYS
127 .allocate_physical(BASE, n(1))
128 .expect("single-frame alloc");
129 let block = PHYS
130 .allocate_physical(BASE, n(4))
131 .expect("4-frame contiguous alloc");
132 println!("\nallocate_physical(1 frame) -> {single:#x}");
133 println!("allocate_physical(4 frames) -> {block:#x}");
134 print_stats("with 5 frames out", &PHYS);
135
136 // SAFETY: each address came from `allocate_physical` with the same page size
137 // and count and is not used afterwards.
138 unsafe {
139 PHYS.deallocate_physical(BASE, n(1), single);
140 PHYS.deallocate_physical(BASE, n(4), block);
141 }
142 println!("\nfreed both — buddies merge back.");
143 print_stats("after free", &PHYS);
144
145 // Composition: a per-CPU magazine + shared depot over a fresh SummaryBuddy:
146 compose_with_depot();
147}
148
149/// Wrap a `SummaryBuddyAllocator` in a [`DepotAllocator`].
150fn compose_with_depot() {
151 /// Uniprocessor selector: every CPU maps to slot 0. A real kernel returns an
152 /// APIC id / `TPIDR_EL1` here.
153 struct OneCpu;
154 impl CpuId for OneCpu {
155 fn current_cpu() -> usize {
156 0
157 }
158 }
159 const SLOTS: usize = 8; // magazines (>= CPUs you want disjoint)
160
161 // Same const-new composability: the whole stack is one `static`-able value.
162 let mag: DepotAllocator<SummaryBuddyAllocator<ORDERS, IdentityProv>, OneCpu, SLOTS> =
163 DepotAllocator::new(BASE, SummaryBuddyAllocator::new(BASE));
164
165 let pool = Region::new(SPAN_FRAMES * BASE.bytes(), MAX_BLOCK);
166 // SAFETY: as above; here the whole region is usable, so the single-range
167 // convenience applies.
168 unsafe { mag.init_region(pool.addr(), SPAN_FRAMES * BASE.bytes()) };
169
170 println!("\n── DepotAllocator<SummaryBuddyAllocator> ──");
171 let a = mag.allocate_physical(BASE, n(1)).expect("mag alloc");
172 // SAFETY: `a` came from this allocator; freed once, then not reused by us.
173 unsafe { mag.deallocate_physical(BASE, n(1), a) };
174 let b = mag.allocate_physical(BASE, n(1)).expect("mag re-alloc");
175 println!("alloc {a:#x} -> free -> alloc {b:#x}");
176 assert_eq!(a, b, "the magazine should return the just-freed frame");
177 println!("re-alloc returned the cached frame (no backend round-trip).");
178 // SAFETY: final free of a live frame.
179 unsafe { mag.deallocate_physical(BASE, n(1), b) };
180}Sourcepub const fn total_bytes(self, count: NonZeroUsize) -> Option<usize>
pub const fn total_bytes(self, count: NonZeroUsize) -> Option<usize>
Total bytes for count frames of this size.
Returns None on overflow.
Sourcepub const fn is_aligned(self, addr: usize) -> bool
pub const fn is_aligned(self, addr: usize) -> bool
True if addr is naturally aligned to this page size.
Sourcepub const fn align_down(self, addr: usize) -> usize
pub const fn align_down(self, addr: usize) -> usize
Round addr down to the nearest aligned frame base.
Trait Implementations§
impl Copy for PageSize
impl Eq for PageSize
Source§impl Ord for PageSize
impl Ord for PageSize
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Compares and returns the maximum of two values. Read more
Source§impl PartialOrd for PageSize
impl PartialOrd for PageSize
impl StructuralPartialEq for PageSize
Auto Trait Implementations§
impl Freeze for PageSize
impl RefUnwindSafe for PageSize
impl Send for PageSize
impl Sync for PageSize
impl Unpin for PageSize
impl UnsafeUnpin for PageSize
impl UnwindSafe for PageSize
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more