mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 05:46:48 +00:00
Replace frame allocator with buddy system allocator
This commit is contained in:
parent
7fa72d2c3e
commit
91b9501a1b
@ -1,78 +1,58 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use spin::Mutex;
|
use buddy_system_allocator::FrameAllocator;
|
||||||
|
use limine::{LimineMemmapEntry, LimineMemoryMapEntryType};
|
||||||
|
use log::info;
|
||||||
|
use spin::{Mutex, Once};
|
||||||
|
|
||||||
use crate::{config::PAGE_SIZE, vm::Paddr};
|
use crate::{config::PAGE_SIZE, vm::Paddr};
|
||||||
|
|
||||||
use super::address::PhysAddr;
|
use super::address::PhysAddr;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
static FRAME_ALLOCATOR: Once<Mutex<FrameAllocator>> = Once::new();
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref FRAME_ALLOCATOR: Mutex<FreeListAllocator> = Mutex::new(FreeListAllocator {
|
|
||||||
current: 0,
|
|
||||||
end: 0,
|
|
||||||
free_list: Vec::new(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
trait FrameAllocator {
|
|
||||||
fn alloc(&mut self) -> Option<usize>;
|
|
||||||
fn dealloc(&mut self, value: usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FreeListAllocator {
|
|
||||||
current: usize,
|
|
||||||
end: usize,
|
|
||||||
free_list: Vec<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FreeListAllocator {
|
|
||||||
fn alloc(&mut self) -> Option<usize> {
|
|
||||||
let mut ret = 0;
|
|
||||||
if let Some(x) = self.free_list.pop() {
|
|
||||||
ret = x;
|
|
||||||
} else if self.current < self.end {
|
|
||||||
ret = self.current;
|
|
||||||
self.current += PAGE_SIZE;
|
|
||||||
};
|
|
||||||
Some(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dealloc(&mut self, value: usize) {
|
|
||||||
assert!(!self.free_list.contains(&value));
|
|
||||||
self.free_list.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
// #[repr(transparent)]
|
// #[repr(transparent)]
|
||||||
pub struct PhysFrame {
|
pub struct PhysFrame {
|
||||||
start_pa: usize,
|
frame_index: usize,
|
||||||
|
need_dealloc: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhysFrame {
|
impl PhysFrame {
|
||||||
pub const fn start_pa(&self) -> PhysAddr {
|
pub const fn start_pa(&self) -> PhysAddr {
|
||||||
PhysAddr(self.start_pa)
|
PhysAddr(self.frame_index * PAGE_SIZE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn end_pa(&self) -> PhysAddr {
|
pub const fn end_pa(&self) -> PhysAddr {
|
||||||
PhysAddr(self.start_pa + PAGE_SIZE)
|
PhysAddr((self.frame_index + 1) * PAGE_SIZE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc() -> Option<Self> {
|
pub fn alloc() -> Option<Self> {
|
||||||
FRAME_ALLOCATOR
|
FRAME_ALLOCATOR.get().unwrap().lock().alloc(1).map(|pa| Self {
|
||||||
.lock()
|
frame_index: pa,
|
||||||
.alloc()
|
need_dealloc: true,
|
||||||
.map(|pa| Self { start_pa: pa })
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alloc_continuous_range(frame_count: usize) -> Option<Vec<Self>> {
|
||||||
|
FRAME_ALLOCATOR.get().unwrap().lock().alloc(frame_count).map(|start| {
|
||||||
|
let mut vector = Vec::new();
|
||||||
|
for i in 0..frame_count {
|
||||||
|
vector.push(Self {
|
||||||
|
frame_index: start + i,
|
||||||
|
need_dealloc: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
vector
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_with_paddr(paddr: Paddr) -> Option<Self> {
|
pub fn alloc_with_paddr(paddr: Paddr) -> Option<Self> {
|
||||||
// FIXME: need to check whether the physical address is invalid or not
|
// FIXME: need to check whether the physical address is invalid or not
|
||||||
Some(Self { start_pa: paddr })
|
Some(Self {
|
||||||
}
|
frame_index: paddr / PAGE_SIZE,
|
||||||
|
need_dealloc: false,
|
||||||
pub fn dealloc(pa: usize) {
|
})
|
||||||
FRAME_ALLOCATOR.lock().dealloc(pa)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_zero() -> Option<Self> {
|
pub fn alloc_zero() -> Option<Self> {
|
||||||
@ -92,11 +72,27 @@ impl PhysFrame {
|
|||||||
|
|
||||||
impl Drop for PhysFrame {
|
impl Drop for PhysFrame {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
FRAME_ALLOCATOR.lock().dealloc(self.start_pa);
|
if self.need_dealloc {
|
||||||
|
FRAME_ALLOCATOR.get().unwrap().lock().dealloc(self.frame_index, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn init(start: usize, size: usize) {
|
pub(crate) fn init(regions: &Vec<&LimineMemmapEntry>) {
|
||||||
FRAME_ALLOCATOR.lock().current = start;
|
let mut allocator = FrameAllocator::<32>::new();
|
||||||
FRAME_ALLOCATOR.lock().end = start + size;
|
for region in regions.iter() {
|
||||||
}
|
if region.typ == LimineMemoryMapEntryType::Usable {
|
||||||
|
assert_eq!(region.base % PAGE_SIZE as u64, 0);
|
||||||
|
assert_eq!(region.len % PAGE_SIZE as u64, 0);
|
||||||
|
let start = region.base as usize / PAGE_SIZE;
|
||||||
|
let end = start + region.len as usize / PAGE_SIZE;
|
||||||
|
allocator.add_frame(start, end);
|
||||||
|
info!(
|
||||||
|
"Found usable region, start:{:x}, end:{:x}",
|
||||||
|
region.base,
|
||||||
|
region.base + region.len
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FRAME_ALLOCATOR.call_once(||Mutex::new(allocator));
|
||||||
|
}
|
@ -56,20 +56,8 @@ pub(crate) fn init() {
|
|||||||
debug!("Found memory region:{:x?}", **i);
|
debug!("Found memory region:{:x?}", **i);
|
||||||
memory_regions.push(&**i);
|
memory_regions.push(&**i);
|
||||||
}
|
}
|
||||||
let mut biggest_region_size = 0;
|
|
||||||
let mut biggest_region_start = 0;
|
|
||||||
for i in memory_regions.iter() {
|
|
||||||
if i.len > biggest_region_size {
|
|
||||||
biggest_region_size = i.len;
|
|
||||||
biggest_region_start = i.base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if biggest_region_size == 0 {
|
|
||||||
panic!("Cannot find usable memory region");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: pass the memory regions to the frame allocator. The frame allocator should use multiple usable area
|
frame_allocator::init(&memory_regions);
|
||||||
frame_allocator::init(biggest_region_start as usize, biggest_region_size as usize);
|
|
||||||
page_table::init();
|
page_table::init();
|
||||||
|
|
||||||
MEMORY_REGIONS.call_once(|| memory_regions);
|
MEMORY_REGIONS.call_once(|| memory_regions);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user