rslab/
lib.rs

1#![feature(allocator_api)]
2#![feature(nonnull_slice_from_raw_parts)]
3#![feature(alloc_layout_extra)]
4#![allow(irrefutable_let_patterns)]
5#![no_std]
6#![allow(unused)]
7
8#[macro_use]
9extern crate log;
10extern crate alloc;
11mod formation;
12mod kmalloc;
13mod slab;
14
15use crate::formation::SlabError;
16use crate::slab::{create_mem_cache, MemCache, SlabInfo};
17use core::marker::PhantomData;
18use doubly_linked_list::*;
19use preprint::pprintln;
20
21pub use crate::slab::{print_slab_system_info};
22pub use kmalloc::SlabAllocator;
23
24/// Cache链表头
25static mut SLAB_CACHES: ListHead = ListHead::new();
26static mut MEM_CACHE_BOOT: MemCache = MemCache::new();
27
28/// 默认frame_size大小:0x1000 4k
29static mut FRAME_SIZE: usize = 0x1000;
30/// 默认cache_line_size大小:16
31static mut CACHE_LINE_SIZE: usize = 16;
32
33#[inline]
34fn frame_size() -> usize {
35    unsafe { FRAME_SIZE }
36}
37
38#[inline]
39fn cls() -> usize {
40    unsafe { CACHE_LINE_SIZE }
41}
42
43extern "C" {
44    /// 用户需要向slab系统提供获取frame的接口
45    fn alloc_frames(num: usize) -> *mut u8;
46    /// 用户需要向slab系统提供释放frame的接口
47    fn free_frames(addr: *mut u8, num: usize);
48    /// 对于多核cpu,需要用户提供一个获取当前cpu id的接口
49    fn current_cpu_id() -> usize;
50}
51
52/// 初始化slab系统,需要知道frame_size与cache_line_size
53pub fn init_slab_system(frame_size: usize, cache_line_size: usize) {
54    init_slab_info(frame_size, cache_line_size);
55    /// 初始化slab系统的两个基本cache
56    slab::mem_cache_init();
57    /// 初始化常用的Cache
58    kmalloc::init_kmalloc();
59}
60
61/// 设置slab系统的基本信息
62#[inline]
63fn init_slab_info(frame_size: usize, cache_line_size: usize) {
64    unsafe {
65        FRAME_SIZE = frame_size;
66        CACHE_LINE_SIZE = cache_line_size;
67    }
68}
69
70/// 自定义对象
71///
72/// 其需要实现一个构造函数,用于初始化分配的内存
73pub trait Object {
74    fn construct() -> Self;
75}
76
77/// 对象分配器接口,用于专门分配用户自定义对象
78pub trait ObjectAllocator<T: Object> {
79    /// 分配一个对象,返回对象的可变引用,如果分配失败则返回失败原因
80    fn alloc(&self) -> Result<&mut T,SlabError>;
81    /// 释放一个对象,如果释放失败则返回失败原因
82    fn dealloc(&self, obj: &mut T) -> Result<(), SlabError>;
83    /// 销毁对象分配器
84    fn destroy(&mut self);
85}
86
87pub struct SlabCache<T: Object> {
88    cache: &'static mut MemCache,
89    obj_type: PhantomData<T>,
90}
91
92impl<T: Object> SlabCache<T> {
93    pub fn new(name: &'static str) -> Result<SlabCache<T>, SlabError> {
94        let size = core::mem::size_of::<T>() as u32;
95        let align = core::mem::align_of::<T>() as u32;
96        let cache = create_mem_cache(name, size, align)?;
97        Ok(SlabCache {
98            cache,
99            obj_type: PhantomData,
100        })
101    }
102    pub fn print_info(&self) {
103        self.cache.print_info();
104    }
105    pub fn get_cache_info(&self)->SlabInfo{
106        self.cache.get_cache_info()
107    }
108}
109
110impl<T: Object> ObjectAllocator<T> for SlabCache<T> {
111    fn alloc(&self) -> Result<&mut T,SlabError> {
112        let obj_ptr = self.cache.alloc()?;
113        unsafe {
114            let obj = obj_ptr as *mut T;
115            obj.write(T::construct());
116            Ok(&mut *obj)
117        }
118    }
119    fn dealloc(&self, obj: &mut T) -> Result<(), SlabError> {
120        self.cache.dealloc(obj as *mut T as *mut u8)
121    }
122    fn destroy(&mut self) {
123        self.cache.destroy();
124    }
125}