1use hal::mem::PhysAddr;
4
5use crate::error::Result;
6use crate::sync::spinlock::SpinLocked;
7use crate::types::boxed::Box;
8
9use core::pin::Pin;
10
11mod bitset;
12
13pub const PAGE_SIZE: usize = 4096;
15
16const PAGE_CNT: usize = 100; type AllocatorType = bitset::Allocator<PAGE_CNT>;
19
20static PFA: SpinLocked<Option<Pin<Box<AllocatorType>>>> = SpinLocked::new(None);
21
22trait Allocator<const N: usize> {
24 fn initializer() -> unsafe fn(PhysAddr, usize) -> Result<Pin<Box<Self>>>;
31
32 fn alloc(&mut self, page_count: usize) -> Option<PhysAddr>;
33 #[allow(dead_code)]
34 fn free(&mut self, addr: PhysAddr, page_count: usize);
35}
36
37pub fn init_pfa(addr: PhysAddr) -> Result<()> {
38 let mut pfa = PFA.lock();
39 if pfa.is_some() {
40 return Err(kerr!(InvalidArgument));
41 }
42
43 let initializer = AllocatorType::initializer();
44 *pfa = Some(unsafe { initializer(addr, PAGE_CNT)? });
45
46 Ok(())
47}
48
49pub fn alloc_page(page_count: usize) -> Option<PhysAddr> {
50 let mut pfa = PFA.lock();
51 pfa.as_mut()?.alloc(page_count)
52}
53
54#[allow(dead_code)]
55pub fn free_page(addr: PhysAddr, page_count: usize) {
56 let mut pfa = PFA.lock();
57 if let Some(pfa) = pfa.as_mut() {
58 pfa.free(addr, page_count);
59 }
60}