#![feature(allocator_api)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(alloc_layout_extra)]
#![allow(irrefutable_let_patterns)]
#![no_std]
#![allow(unused)]
#[macro_use]
extern crate log;
extern crate alloc;
mod formation;
mod kmalloc;
mod slab;
use crate::formation::SlabError;
use crate::slab::{create_mem_cache, MemCache, SlabInfo};
use core::marker::PhantomData;
use doubly_linked_list::*;
use preprint::pprintln;
pub use crate::slab::{print_slab_system_info};
pub use kmalloc::SlabAllocator;
static mut SLAB_CACHES: ListHead = ListHead::new();
static mut MEM_CACHE_BOOT: MemCache = MemCache::new();
static mut FRAME_SIZE: usize = 0x1000;
static mut CACHE_LINE_SIZE: usize = 16;
#[inline]
fn frame_size() -> usize {
unsafe { FRAME_SIZE }
}
#[inline]
fn cls() -> usize {
unsafe { CACHE_LINE_SIZE }
}
extern "C" {
fn alloc_frames(num: usize) -> *mut u8;
fn free_frames(addr: *mut u8, num: usize);
fn current_cpu_id() -> usize;
}
pub fn init_slab_system(frame_size: usize, cache_line_size: usize) {
init_slab_info(frame_size, cache_line_size);
slab::mem_cache_init();
kmalloc::init_kmalloc();
}
#[inline]
fn init_slab_info(frame_size: usize, cache_line_size: usize) {
unsafe {
FRAME_SIZE = frame_size;
CACHE_LINE_SIZE = cache_line_size;
}
}
pub trait Object {
fn construct() -> Self;
}
pub trait ObjectAllocator<T: Object> {
fn alloc(&self) -> Result<&mut T,SlabError>;
fn dealloc(&self, obj: &mut T) -> Result<(), SlabError>;
fn destroy(&mut self);
}
pub struct SlabCache<T: Object> {
cache: &'static mut MemCache,
obj_type: PhantomData<T>,
}
impl<T: Object> SlabCache<T> {
pub fn new(name: &'static str) -> Result<SlabCache<T>, SlabError> {
let size = core::mem::size_of::<T>() as u32;
let align = core::mem::align_of::<T>() as u32;
let cache = create_mem_cache(name, size, align)?;
Ok(SlabCache {
cache,
obj_type: PhantomData,
})
}
pub fn print_info(&self) {
self.cache.print_info();
}
pub fn get_cache_info(&self)->SlabInfo{
self.cache.get_cache_info()
}
}
impl<T: Object> ObjectAllocator<T> for SlabCache<T> {
fn alloc(&self) -> Result<&mut T,SlabError> {
let obj_ptr = self.cache.alloc()?;
unsafe {
let obj = obj_ptr as *mut T;
obj.write(T::construct());
Ok(&mut *obj)
}
}
fn dealloc(&self, obj: &mut T) -> Result<(), SlabError> {
self.cache.dealloc(obj as *mut T as *mut u8)
}
fn destroy(&mut self) {
self.cache.destroy();
}
}