mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: add freelist allocator
This commit is contained in:
parent
f74c7fbc92
commit
1034cdb003
@ -6,16 +6,22 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
default = ["arch_riscv64", "board_virt", "log_color"]
|
||||
default = ["arch_riscv64", "board_virt", "log_color", "frame_freelist"]
|
||||
|
||||
arch_riscv64 = []
|
||||
arch_riscv32 = []
|
||||
arch_arm = []
|
||||
arch_x86 = []
|
||||
|
||||
board_default = []
|
||||
board_virt = []
|
||||
board_thead = []
|
||||
|
||||
log_color = []
|
||||
|
||||
frame_bitmap = []
|
||||
frame_freelist = []
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
use core::fmt::{Debug, Display, Formatter, LowerHex, Result, UpperHex};
|
||||
use core::hash::Hash;
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
||||
|
||||
#[inline(always)]
|
||||
@ -12,14 +13,17 @@ fn align_down(addr: usize, align: usize) -> usize {
|
||||
addr & !(align - 1)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PhysAddr(pub usize);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct VirtAddr(pub usize);
|
||||
|
||||
pub trait AddressOps {
|
||||
fn as_u32(&self) -> u32;
|
||||
fn as_u64(&self) -> u64;
|
||||
fn as_usize(&self) -> usize;
|
||||
fn as_non_zero_usize(&self) -> Option<NonZeroUsize>;
|
||||
fn align_up<T>(&self, align: T) -> Self
|
||||
where
|
||||
T: Into<usize>;
|
||||
@ -51,6 +55,10 @@ impl AddressOps for PhysAddr {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn as_non_zero_usize(&self) -> Option<NonZeroUsize> {
|
||||
NonZeroUsize::new(self.0)
|
||||
}
|
||||
|
||||
fn align_up<T>(&self, align: T) -> Self
|
||||
where
|
||||
T: Into<usize>,
|
||||
@ -79,6 +87,10 @@ impl AddressOps for VirtAddr {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn as_non_zero_usize(&self) -> Option<NonZeroUsize> {
|
||||
NonZeroUsize::new(self.0)
|
||||
}
|
||||
|
||||
fn align_up<T>(&self, align: T) -> Self
|
||||
where
|
||||
T: Into<usize>,
|
||||
@ -162,6 +174,18 @@ impl From<PhysAddr> for usize {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NonZeroUsize> for PhysAddr {
|
||||
fn from(addr: NonZeroUsize) -> Self {
|
||||
PhysAddr(addr.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PhysAddr> for NonZeroUsize {
|
||||
fn from(addr: PhysAddr) -> Self {
|
||||
NonZeroUsize::new(addr.0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for VirtAddr {
|
||||
fn from(addr: usize) -> Self {
|
||||
VirtAddr(addr)
|
||||
@ -174,6 +198,18 @@ impl From<VirtAddr> for usize {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NonZeroUsize> for VirtAddr {
|
||||
fn from(addr: NonZeroUsize) -> Self {
|
||||
VirtAddr(addr.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VirtAddr> for NonZeroUsize {
|
||||
fn from(addr: VirtAddr) -> Self {
|
||||
NonZeroUsize::new(addr.0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for PhysAddr {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
write!(f, "PhysAddr({:#x})", self.0)
|
||||
|
@ -1,31 +1,78 @@
|
||||
#[allow(unused_imports)]
|
||||
use lazy_static::lazy_static;
|
||||
use log::trace;
|
||||
use spin::mutex::SpinMutex;
|
||||
|
||||
use crate::arch::layout::*;
|
||||
use crate::mm::addr::{AddressOps, PhysAddr};
|
||||
#[allow(unused_imports)]
|
||||
use crate::mm::bitmap::{Bitmap1K, BitmapOps};
|
||||
#[allow(unused_imports)]
|
||||
use crate::mm::freelist::FreeList;
|
||||
|
||||
// TODO: allow to switch allocator between `BitmapXX` and `FreeList`
|
||||
// 1k * 4k = 4MB, currently enough for kernel data
|
||||
#[cfg(feature = "frame_bitmap")]
|
||||
static ALLOCATOR: SpinMutex<Bitmap1K> = SpinMutex::new(Bitmap1K::DEFAULT);
|
||||
|
||||
pub trait FrameOps {
|
||||
fn alloc(&self) -> Option<PhysAddr>;
|
||||
fn dealloc(&self, addr: PhysAddr);
|
||||
#[cfg(feature = "frame_freelist")]
|
||||
lazy_static! {
|
||||
static ref ALLOCATOR: SpinMutex<FreeList> = {
|
||||
let mut list = FreeList::new();
|
||||
|
||||
for i in 0..1024 {
|
||||
let addr = PhysAddr((i * PAGE_SIZE) + KERNEL_MEM_START);
|
||||
list.push(addr.into());
|
||||
}
|
||||
|
||||
SpinMutex::new(list)
|
||||
};
|
||||
}
|
||||
|
||||
pub struct FrameAllocator;
|
||||
|
||||
impl FrameOps for FrameAllocator {
|
||||
fn alloc(&self) -> Option<PhysAddr> {
|
||||
ALLOCATOR
|
||||
.lock()
|
||||
.alloc()
|
||||
.map(|i| PhysAddr((i * PAGE_SIZE) + KERNEL_MEM_START))
|
||||
impl FrameAllocator {
|
||||
pub fn alloc(&self) -> Option<PhysAddr> {
|
||||
#[cfg(feature = "frame_bitmap")]
|
||||
let addr = crate::mm::frame::ALLOCATOR.lock().alloc().map(|i| {
|
||||
crate::mm::addr::PhysAddr(
|
||||
(i * crate::arch::arch::mm::page::PAGE_SIZE)
|
||||
+ crate::arch::arch::layout::KERNEL_MEM_START,
|
||||
)
|
||||
});
|
||||
|
||||
#[cfg(feature = "frame_freelist")]
|
||||
let addr = ALLOCATOR.lock().pop().map(|addr| addr.into());
|
||||
|
||||
trace!("[mm/frame] alloc frame: {:?}", addr);
|
||||
fill_mem(addr, 0xaa);
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
fn dealloc(&self, addr: PhysAddr) {
|
||||
ALLOCATOR
|
||||
.lock()
|
||||
.dealloc((addr.as_usize() - KERNEL_MEM_START) / PAGE_SIZE);
|
||||
pub fn dealloc(&self, addr: PhysAddr) {
|
||||
debug_assert!(addr.is_aligned(PAGE_SIZE));
|
||||
debug_assert!(addr.as_usize() >= KERNEL_MEM_START);
|
||||
|
||||
trace!("[mm/frame] dealloc frame: {:?}", addr);
|
||||
fill_mem(Some(addr), 0x55);
|
||||
|
||||
#[cfg(feature = "frame_bitmap")]
|
||||
crate::mm::frame::ALLOCATOR.lock().dealloc(
|
||||
(addr.as_usize() - crate::arch::arch::layout::KERNEL_MEM_START)
|
||||
/ crate::arch::arch::mm::page::PAGE_SIZE,
|
||||
);
|
||||
|
||||
#[cfg(feature = "frame_freelist")]
|
||||
ALLOCATOR.lock().push(addr.into());
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_mem(addr: Option<PhysAddr>, val: u8) {
|
||||
#[cfg(debug_assertions)]
|
||||
unsafe {
|
||||
// fill with junks
|
||||
if let Some(addr) = addr {
|
||||
core::ptr::write_bytes(addr.as_usize() as *mut u8, val, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
29
src/mm/freelist.rs
Normal file
29
src/mm/freelist.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
pub struct FreeList {
|
||||
next: Option<NonZeroUsize>,
|
||||
}
|
||||
|
||||
impl FreeList {
|
||||
pub const fn new() -> Self {
|
||||
Self { next: None }
|
||||
}
|
||||
|
||||
pub fn push(&mut self, ptr: NonZeroUsize) {
|
||||
unsafe {
|
||||
let raw: *mut usize = ptr.get() as *mut usize;
|
||||
*raw = self.next.map_or(0, |next| next.get());
|
||||
}
|
||||
self.next = Some(ptr);
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<NonZeroUsize> {
|
||||
let popped = self.next.take();
|
||||
if let Some(next) = popped {
|
||||
let raw: *const usize = next.get() as *const usize;
|
||||
self.next = NonZeroUsize::new(unsafe { *raw });
|
||||
}
|
||||
|
||||
popped
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod addr;
|
||||
mod bitmap;
|
||||
pub mod frame;
|
||||
mod freelist;
|
||||
pub mod page;
|
||||
|
Loading…
Reference in New Issue
Block a user