forked from chyyuu/os_kernel_lab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathallocator.rs
50 lines (44 loc) · 1.58 KB
/
allocator.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//! 提供帧分配器 [`FRAME_ALLOCATOR`](FrameAllocator)
//!
//! 返回的 [`FrameTracker`] 类型代表一个帧,它在被 drop 时会自动将空间补回分配器中。
use super::*;
use crate::memory::*;
use algorithm::*;
use lazy_static::*;
use spin::Mutex;
lazy_static! {
/// 帧分配器
pub static ref FRAME_ALLOCATOR: Mutex<FrameAllocator<AllocatorImpl>> = Mutex::new(FrameAllocator::new(Range::from(
PhysicalPageNumber::ceil(PhysicalAddress::from(*KERNEL_END_ADDRESS))..PhysicalPageNumber::floor(MEMORY_END_ADDRESS),
)
));
}
/// 基于线段树的帧分配 / 回收
pub struct FrameAllocator<T: Allocator> {
/// 可用区间的起始
start_ppn: PhysicalPageNumber,
/// 分配器
allocator: T,
}
impl<T: Allocator> FrameAllocator<T> {
/// 创建对象
pub fn new(range: impl Into<Range<PhysicalPageNumber>> + Copy) -> Self {
FrameAllocator {
start_ppn: range.into().start,
allocator: T::new(range.into().len()),
}
}
/// 分配帧,如果没有剩余则返回 `Err`
pub fn alloc(&mut self) -> MemoryResult<FrameTracker> {
self.allocator
.alloc()
.ok_or("no available frame to allocate")
.map(|offset| FrameTracker(self.start_ppn + offset))
}
/// 将被释放的帧添加到空闲列表的尾部
///
/// 这个函数会在 [`FrameTracker`] 被 drop 时自动调用,不应在其他地方调用
pub(super) fn dealloc(&mut self, frame: &FrameTracker) {
self.allocator.dealloc(frame.page_number() - self.start_ppn);
}
}