mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 17:55:20 +08:00
feat: move allocator into lib
This commit is contained in:
parent
bed9baac4b
commit
4d090c0478
@ -1,7 +0,0 @@
|
|||||||
mod bitmap;
|
|
||||||
mod block;
|
|
||||||
mod freelist;
|
|
||||||
|
|
||||||
pub use bitmap::*;
|
|
||||||
pub use block::*;
|
|
||||||
pub use freelist::*;
|
|
127
lib/allocator/Cargo.lock
generated
Normal file
127
lib/allocator/Cargo.lock
generated
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"spin",
|
||||||
|
"static_assertions",
|
||||||
|
"utils",
|
||||||
|
"vspace",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-derive"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.58"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"vspace",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vspace"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
]
|
11
lib/allocator/Cargo.toml
Normal file
11
lib/allocator/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "allocator"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
vspace = { path = "../vspace" }
|
||||||
|
utils = { path = "../utils" }
|
||||||
|
|
||||||
|
spin = "0.9"
|
||||||
|
static_assertions = "1.1"
|
@ -1,11 +1,9 @@
|
|||||||
use crate::arch::layout::PAGE_SIZE;
|
|
||||||
use crate::vspace::addr::{AddressOps, PhysAddr};
|
|
||||||
use core::alloc::{GlobalAlloc, Layout};
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
use core::ptr::null_mut;
|
use core::ptr::null_mut;
|
||||||
use log::warn;
|
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
use vspace::addr::{AddressOps, PhysAddr};
|
||||||
|
|
||||||
trait BitmapCfg: Copy + Clone {
|
pub trait BitmapCfg: Copy + Clone {
|
||||||
const CAPACITY: usize;
|
const CAPACITY: usize;
|
||||||
const DEFAULT: Self;
|
const DEFAULT: Self;
|
||||||
|
|
||||||
@ -14,7 +12,7 @@ trait BitmapCfg: Copy + Clone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Bitmap32(u32);
|
pub struct Bitmap32(u32);
|
||||||
|
|
||||||
impl BitmapCfg for Bitmap32 {
|
impl BitmapCfg for Bitmap32 {
|
||||||
const CAPACITY: usize = u32::BITS as usize;
|
const CAPACITY: usize = u32::BITS as usize;
|
||||||
@ -54,7 +52,7 @@ impl BitmapCfg for Bitmap32 {
|
|||||||
const BITS_PER_LEVEL: usize = 32;
|
const BITS_PER_LEVEL: usize = 32;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Bitmap<B: BitmapCfg> {
|
pub struct Bitmap<B: BitmapCfg> {
|
||||||
bits: u32, // must not overflow with BITS_PER_LEVEL
|
bits: u32, // must not overflow with BITS_PER_LEVEL
|
||||||
next: [B; BITS_PER_LEVEL],
|
next: [B; BITS_PER_LEVEL],
|
||||||
}
|
}
|
||||||
@ -117,9 +115,9 @@ impl<B: BitmapCfg> Bitmap<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1k pages, consumes (32+1)*32/8 = 132 bytes, allocates 1k * 4KiB = 4MiB memory
|
// 1k pages, consumes (32+1)*32/8 = 132 bytes, allocates 1k * 4KiB = 4MiB memory
|
||||||
type Bitmap1K = Bitmap<Bitmap32>;
|
pub type Bitmap1K = Bitmap<Bitmap32>;
|
||||||
// 32k pages, consumes (32*(32+1)+1)*32/8 = 4228 bytes, allocates 32k * 4KiB = 128MiB memory
|
// 32k pages, consumes (32*(32+1)+1)*32/8 = 4228 bytes, allocates 32k * 4KiB = 128MiB memory
|
||||||
type Bitmap32K = Bitmap<Bitmap1K>;
|
pub type Bitmap32K = Bitmap<Bitmap1K>;
|
||||||
|
|
||||||
const_assert_eq!(core::mem::size_of::<Bitmap1K>(), (32 + 1) * 32 / 8);
|
const_assert_eq!(core::mem::size_of::<Bitmap1K>(), (32 + 1) * 32 / 8);
|
||||||
const_assert_eq!(
|
const_assert_eq!(
|
||||||
@ -127,21 +125,21 @@ const_assert_eq!(
|
|||||||
(32 * (32 + 1) + 1) * 32 / 8
|
(32 * (32 + 1) + 1) * 32 / 8
|
||||||
);
|
);
|
||||||
|
|
||||||
struct BitmapAllocator<B: BitmapCfg = Bitmap32K> {
|
pub struct BitmapAllocator<B: BitmapCfg = Bitmap32K> {
|
||||||
bitmap: Mutex<B>,
|
bitmap: Mutex<B>,
|
||||||
base: PhysAddr,
|
base: PhysAddr,
|
||||||
|
granularity: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<B: BitmapCfg> GlobalAlloc for BitmapAllocator<B> {
|
unsafe impl<B: BitmapCfg> GlobalAlloc for BitmapAllocator<B> {
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
if layout.size() > PAGE_SIZE || layout.align() > PAGE_SIZE {
|
if layout.size() > self.granularity || layout.align() > self.granularity {
|
||||||
warn!("unsupported layout: {:?}, page size: {}", layout, PAGE_SIZE);
|
|
||||||
return null_mut();
|
return null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
let bit = self.bitmap.lock().alloc_bits();
|
let bit = self.bitmap.lock().alloc_bits();
|
||||||
if let Some(index) = bit {
|
if let Some(index) = bit {
|
||||||
let addr = self.base + index * PAGE_SIZE;
|
let addr = self.base + index * self.granularity;
|
||||||
return addr.as_mut_ptr();
|
return addr.as_mut_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,16 +147,17 @@ unsafe impl<B: BitmapCfg> GlobalAlloc for BitmapAllocator<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {
|
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {
|
||||||
let bit = (PhysAddr::from(ptr) - self.base).as_usize() / PAGE_SIZE;
|
let bit = (PhysAddr::from(ptr) - self.base).as_usize() / self.granularity;
|
||||||
self.bitmap.lock().dealloc_bits(bit);
|
self.bitmap.lock().dealloc_bits(bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: BitmapCfg> BitmapAllocator<B> {
|
impl<B: BitmapCfg> BitmapAllocator<B> {
|
||||||
pub fn new(base: PhysAddr) -> Self {
|
pub fn new(base: PhysAddr, granularity: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bitmap: Mutex::new(B::DEFAULT),
|
bitmap: Mutex::new(B::DEFAULT),
|
||||||
base,
|
base,
|
||||||
|
granularity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,9 +167,8 @@ pub type BitmapAllocator32K = BitmapAllocator<Bitmap32K>;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::arch::layout::PAGE_LAYOUT;
|
|
||||||
|
|
||||||
#[test_case]
|
#[test]
|
||||||
fn test_bitmap32() {
|
fn test_bitmap32() {
|
||||||
let mut bitmap = Bitmap32::DEFAULT;
|
let mut bitmap = Bitmap32::DEFAULT;
|
||||||
|
|
||||||
@ -196,7 +194,7 @@ mod tests {
|
|||||||
assert_eq!(bitmap.alloc_bits(), None);
|
assert_eq!(bitmap.alloc_bits(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case]
|
#[test]
|
||||||
fn test_bitmap1k() {
|
fn test_bitmap1k() {
|
||||||
let mut bitmap = Bitmap1K::DEFAULT;
|
let mut bitmap = Bitmap1K::DEFAULT;
|
||||||
|
|
||||||
@ -221,7 +219,7 @@ mod tests {
|
|||||||
assert_eq!(bitmap.alloc_bits(), None);
|
assert_eq!(bitmap.alloc_bits(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case]
|
#[test]
|
||||||
fn test_bitmap32k() {
|
fn test_bitmap32k() {
|
||||||
let mut bitmap = Bitmap32K::DEFAULT;
|
let mut bitmap = Bitmap32K::DEFAULT;
|
||||||
|
|
||||||
@ -256,27 +254,29 @@ mod tests {
|
|||||||
assert_eq!(bitmap.alloc_bits(), None);
|
assert_eq!(bitmap.alloc_bits(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case]
|
#[test]
|
||||||
fn test_bitmap_allocator() {
|
fn test_bitmap_allocator() {
|
||||||
let allocator = BitmapAllocator32K::new(PhysAddr(0x42));
|
let page_size: usize = 4 * utils::size::KIB;
|
||||||
|
let page_layout = core::alloc::Layout::from_size_align(page_size, page_size).unwrap();
|
||||||
|
let allocator = BitmapAllocator32K::new(PhysAddr(0x42), page_size);
|
||||||
|
|
||||||
// alloc from empty
|
// alloc from empty
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
let ptr = unsafe { allocator.alloc(page_layout) };
|
||||||
assert_eq!(PhysAddr::from(ptr).as_usize(), 0x42 + i * PAGE_SIZE);
|
assert_eq!(PhysAddr::from(ptr).as_usize(), 0x42 + i * page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dealloc
|
// dealloc
|
||||||
for i in 0..16 {
|
for i in 0..16 {
|
||||||
unsafe {
|
unsafe {
|
||||||
allocator.dealloc(PhysAddr(0x42 + i * 2 * PAGE_SIZE).as_mut_ptr(), PAGE_LAYOUT);
|
allocator.dealloc(PhysAddr(0x42 + i * 2 * page_size).as_mut_ptr(), page_layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// predictable alloc from dealloc pattern
|
// predictable alloc from dealloc pattern
|
||||||
for i in 0..16 {
|
for i in 0..16 {
|
||||||
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
let ptr = unsafe { allocator.alloc(page_layout) };
|
||||||
assert_eq!(PhysAddr::from(ptr).as_usize(), 0x42 + i * 2 * PAGE_SIZE);
|
assert_eq!(PhysAddr::from(ptr).as_usize(), 0x42 + i * 2 * page_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use crate::vspace::addr::{AddressOps, PhysAddr};
|
|
||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
|
use vspace::addr::{AddressOps, PhysAddr};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct Block {
|
struct Block {
|
||||||
@ -139,11 +139,16 @@ impl<const N: usize> RamBlock<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Default for RamBlock<N> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test_case]
|
#[test]
|
||||||
fn test_block() {
|
fn test_block() {
|
||||||
let mut blk = RamBlock::<4>::new();
|
let mut blk = RamBlock::<4>::new();
|
||||||
blk.dealloc(PhysAddr(0), 100);
|
blk.dealloc(PhysAddr(0), 100);
|
||||||
@ -185,7 +190,7 @@ mod tests {
|
|||||||
assert_eq!(ptr, None);
|
assert_eq!(ptr, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case]
|
#[test]
|
||||||
fn test_block_reserve() {
|
fn test_block_reserve() {
|
||||||
let mut blk = RamBlock::<4>::new();
|
let mut blk = RamBlock::<4>::new();
|
||||||
blk.dealloc(PhysAddr(0), 100);
|
blk.dealloc(PhysAddr(0), 100);
|
@ -1,10 +1,10 @@
|
|||||||
// adapted from https://os.phil-opp.com/allocator-designs/#linked-list-allocator
|
// adapted from https://os.phil-opp.com/allocator-designs/#linked-list-allocator
|
||||||
|
|
||||||
use crate::utils::then::Then;
|
|
||||||
use crate::vspace::addr::{AddressOps, PhysAddr};
|
|
||||||
use core::alloc::{GlobalAlloc, Layout};
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
use utils::then::Then;
|
||||||
|
use vspace::addr::{AddressOps, PhysAddr};
|
||||||
|
|
||||||
struct ListNode {
|
struct ListNode {
|
||||||
size: usize,
|
size: usize,
|
||||||
@ -88,6 +88,8 @@ impl FreeList {
|
|||||||
(size, layout.align())
|
(size, layout.align())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// Caller must assume that all the memory allocated or deallocated is valid (no overflow or double free)
|
||||||
pub unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 {
|
pub unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 {
|
||||||
let (size, align) = Self::align_layout(layout);
|
let (size, align) = Self::align_layout(layout);
|
||||||
|
|
||||||
@ -103,6 +105,8 @@ impl FreeList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// Caller must assume that all the memory allocated or deallocated is valid (no overflow or double free)
|
||||||
pub unsafe fn dealloc(&mut self, start: PhysAddr, size: usize) {
|
pub unsafe fn dealloc(&mut self, start: PhysAddr, size: usize) {
|
||||||
assert_eq!(start.align_up(core::mem::align_of::<ListNode>()), start);
|
assert_eq!(start.align_up(core::mem::align_of::<ListNode>()), start);
|
||||||
assert!(size >= core::mem::size_of::<ListNode>());
|
assert!(size >= core::mem::size_of::<ListNode>());
|
||||||
@ -135,6 +139,12 @@ impl FreeList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for FreeList {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for FreeList {
|
impl Debug for FreeList {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
let mut current = &self.head;
|
let mut current = &self.head;
|
||||||
@ -174,41 +184,43 @@ unsafe impl GlobalAlloc for FreeListAllocator {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::arch::layout::{PAGE_LAYOUT, PAGE_SIZE};
|
|
||||||
|
|
||||||
// TODO: freelist tests are broken since it requires real free memory to work, ignore for now
|
const PAGE_SIZE: usize = 4 * utils::size::KIB;
|
||||||
|
const PAGE_LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(PAGE_SIZE, PAGE_SIZE) };
|
||||||
|
|
||||||
// #[test_case]
|
#[test]
|
||||||
fn test_freelist() {
|
fn test_freelist() {
|
||||||
const BASE: PhysAddr = PhysAddr(0x80300000);
|
let vec: Vec<u8> = vec![0u8; 33 * PAGE_SIZE];
|
||||||
|
let base = PhysAddr::from(vec.as_ptr()).align_up(PAGE_SIZE);
|
||||||
|
|
||||||
let allocator = FreeListAllocator::new(BASE, 32 * PAGE_SIZE);
|
let allocator = FreeListAllocator::new(base, 32 * PAGE_SIZE);
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
||||||
assert_eq!(ptr as usize, (BASE + i * PAGE_SIZE).as_usize());
|
assert_eq!(ptr as usize, (base + i * PAGE_SIZE).as_usize());
|
||||||
}
|
}
|
||||||
|
|
||||||
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
||||||
assert_eq!(ptr, core::ptr::null_mut());
|
assert_eq!(ptr, core::ptr::null_mut());
|
||||||
|
|
||||||
for i in (0..32).rev() {
|
for i in (0..32).rev() {
|
||||||
let ptr = (BASE + i * PAGE_SIZE).as_mut_ptr();
|
let ptr = (base + i * PAGE_SIZE).as_mut_ptr();
|
||||||
unsafe { allocator.dealloc(ptr, PAGE_LAYOUT) };
|
unsafe { allocator.dealloc(ptr, PAGE_LAYOUT) };
|
||||||
}
|
}
|
||||||
|
|
||||||
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
let ptr = unsafe { allocator.alloc(PAGE_LAYOUT) };
|
||||||
assert_eq!(ptr as usize, BASE.as_usize());
|
assert_eq!(ptr as usize, base.as_usize());
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test_case]
|
#[test]
|
||||||
fn test_freelist_reserve() {
|
fn test_freelist_reserve() {
|
||||||
const BASE: PhysAddr = PhysAddr(0x80300000);
|
let vec: Vec<u8> = vec![0u8; 33 * PAGE_SIZE];
|
||||||
|
let base = PhysAddr::from(vec.as_ptr()).align_up(PAGE_SIZE);
|
||||||
|
|
||||||
let allocator = FreeListAllocator::new(BASE, 32 * PAGE_SIZE);
|
let allocator = FreeListAllocator::new(base, 32 * PAGE_SIZE);
|
||||||
allocator
|
allocator
|
||||||
.list
|
.list
|
||||||
.lock()
|
.lock()
|
||||||
.reserve(BASE + 4 * PAGE_SIZE, 4 * PAGE_SIZE);
|
.reserve(base + 4 * PAGE_SIZE, 4 * PAGE_SIZE);
|
||||||
|
|
||||||
let mut cnt = 32 - 4;
|
let mut cnt = 32 - 4;
|
||||||
loop {
|
loop {
|
||||||
@ -220,11 +232,11 @@ mod tests {
|
|||||||
|
|
||||||
let ptr = PhysAddr::from(ptr);
|
let ptr = PhysAddr::from(ptr);
|
||||||
assert!(
|
assert!(
|
||||||
!(BASE + 4 * PAGE_SIZE <= ptr && ptr < BASE + (4 + 4) * PAGE_SIZE),
|
!(base + 4 * PAGE_SIZE <= ptr && ptr < base + (4 + 4) * PAGE_SIZE),
|
||||||
"Bad alloc: returned ptr: {:?}, reserved range: {:?}->{:?}",
|
"Bad alloc: returned ptr: {:?}, reserved range: {:?}->{:?}",
|
||||||
ptr,
|
ptr,
|
||||||
BASE + 4 * PAGE_SIZE,
|
base + 4 * PAGE_SIZE,
|
||||||
BASE + (4 + 4) * PAGE_SIZE
|
base + (4 + 4) * PAGE_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
cnt -= 1;
|
cnt -= 1;
|
14
lib/allocator/src/lib.rs
Normal file
14
lib/allocator/src/lib.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#![cfg_attr(not(test), no_std)]
|
||||||
|
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate static_assertions;
|
||||||
|
|
||||||
|
mod bitmap;
|
||||||
|
mod block;
|
||||||
|
mod freelist;
|
||||||
|
|
||||||
|
pub use bitmap::*;
|
||||||
|
pub use block::*;
|
||||||
|
pub use freelist::*;
|
Loading…
Reference in New Issue
Block a user