os/mm/frame_allocator/
mod.rs1#![allow(clippy::module_inception)]
4mod frame_allocator;
19
20use alloc::vec::Vec;
21pub use frame_allocator::{FrameRangeTracker, FrameTracker, TrackedFrames};
22
23use crate::mm::{
24 address::{Paddr, PageNum, Ppn, UsizeConvert},
25 frame_allocator::frame_allocator::FRAME_ALLOCATOR,
26};
27
28pub fn init_frame_allocator(start_addr: usize, end_addr: usize) {
35 let start_ppn = Ppn::from_addr_ceil(Paddr::from_usize(start_addr));
37 let end_ppn = Ppn::from_addr_floor(Paddr::from_usize(end_addr));
39
40 let mut allocator = FRAME_ALLOCATOR.lock();
41 allocator.init(start_ppn, end_ppn);
42}
43
44pub fn alloc_frame() -> Option<FrameTracker> {
50 FRAME_ALLOCATOR.lock().alloc_frame()
51}
52
53pub fn alloc_frames(num: usize) -> Option<Vec<FrameTracker>> {
63 FRAME_ALLOCATOR.lock().alloc_frames(num)
64}
65
66pub fn alloc_contig_frames(num: usize) -> Option<FrameRangeTracker> {
76 FRAME_ALLOCATOR.lock().alloc_contig_frames(num)
77}
78
79pub fn alloc_contig_frames_aligned(num: usize, align_pages: usize) -> Option<FrameRangeTracker> {
90 FRAME_ALLOCATOR
91 .lock()
92 .alloc_contig_frames_aligned(num, align_pages)
93}
94
95fn dealloc_frame(frame: &FrameTracker) {
97 FRAME_ALLOCATOR.lock().dealloc_frame(frame);
98}
99
100fn dealloc_frames(frames: &[FrameTracker]) {
102 let mut allocator = FRAME_ALLOCATOR.lock();
103 for frame in frames {
104 allocator.dealloc_frame(frame);
105 }
106}
107
108fn dealloc_contig_frames(frame_range: &FrameRangeTracker) {
110 FRAME_ALLOCATOR.lock().dealloc_contig_frames(frame_range);
111}
112
113pub fn get_total_frames() -> usize {
115 FRAME_ALLOCATOR.lock().total_frames()
116}
117
118pub fn get_allocated_frames() -> usize {
120 FRAME_ALLOCATOR.lock().allocated_frames()
121}
122
123pub fn get_free_frames() -> usize {
125 FRAME_ALLOCATOR.lock().free_frames()
126}
127
128pub fn get_stats() -> (usize, usize, usize, usize, usize) {
137 FRAME_ALLOCATOR.lock().get_stats()
138}
139
140#[cfg(test)]
141mod frame_allocator_tests {
142 use super::*;
143 use crate::{kassert, mm::address::ConvertablePaddr, test_case};
144
145 test_case!(test_single_frame_alloc, {
147 let frame = alloc_frame().expect("分配失败");
148 let ppn = frame.ppn();
149
150 kassert!(ppn.as_usize() > 0);
151
152 let vaddr = ppn.start_addr().to_vaddr();
154 let page_ptr = vaddr.as_ptr::<u64>();
155 unsafe {
156 for i in 0..512 {
157 kassert!(*page_ptr.add(i) == 0);
158 }
159 }
160 });
162
163 test_case!(test_multiple_frames_alloc, {
165 let frames = alloc_frames(5).expect("分配失败");
166 kassert!(frames.len() == 5);
167
168 for frame in &frames {
170 kassert!(frame.ppn().as_usize() > 0);
171 }
172 });
173
174 test_case!(test_contig_frames_alloc, {
176 let frames = alloc_contig_frames(4).expect("分配失败");
177 let start_ppn = frames.range().start().as_usize();
178
179 for i in 0..4 {
181 let expected = start_ppn + i;
182 kassert!(frames.range().start().as_usize() + i == expected);
183 }
184 });
185
186 test_case!(test_frame_auto_reclaim, {
188 let first_ppn = {
190 let frame = alloc_frame().expect("分配失败");
191 frame.ppn()
192 }; let frame2 = alloc_frame().expect("分配失败");
196 kassert!(frame2.ppn() == first_ppn); });
198
199 test_case!(test_aligned_alloc, {
201 let frames = alloc_contig_frames_aligned(4, 16).expect("分配失败");
202 let ppn = frames.range().start().as_usize();
203
204 kassert!(ppn % 16 == 0);
206 });
207
208 test_case!(test_large_alloc, {
210 let frames = alloc_frames(100).expect("分配 100 帧");
211 kassert!(frames.len() == 100);
212 });
213}