1 use core::{alloc::Layout, ptr::NonNull, sync::atomic::AtomicBool}; 2 3 use alloc::boxed::Box; 4 use slabmalloc::*; 5 6 // 全局slab分配器 7 pub(crate) static mut SLABALLOCATOR: Option<SlabAllocator> = None; 8 9 // slab初始化状态 10 pub(crate) static mut SLABINITSTATE: AtomicBool = AtomicBool::new(false); 11 12 /// slab分配器,实际为一堆小的allocator,可以在里面装4K的page 13 /// 利用这些allocator可以为对象分配不同大小的空间 14 pub(crate) struct SlabAllocator { 15 zone: ZoneAllocator<'static>, 16 } 17 18 impl SlabAllocator { 19 /// 创建slab分配器 20 pub fn new() -> SlabAllocator { 21 kdebug!("trying to new a slab_allocator"); 22 SlabAllocator { 23 zone: ZoneAllocator::new(), 24 } 25 } 26 27 /// 为对象(2K以内)分配内存空间 28 pub(crate) unsafe fn allocate(&mut self, layout: Layout) -> *mut u8 { 29 match self.zone.allocate(layout) { 30 Ok(nptr) => nptr.as_ptr(), 31 Err(AllocationError::OutOfMemory) => { 32 let boxed_page = ObjectPage::new(); 33 let leaked_page = Box::leak(boxed_page); 34 self.zone 35 .refill(layout, leaked_page) 36 .expect("Could not refill?"); 37 self.zone 38 .allocate(layout) 39 .expect("Should succeed after refill") 40 .as_ptr() 41 } 42 Err(AllocationError::InvalidLayout) => panic!("Can't allocate this size"), 43 } 44 } 45 46 /// 释放内存空间 47 pub(crate) unsafe fn deallocate( 48 &mut self, 49 ptr: *mut u8, 50 layout: Layout, 51 ) -> Result<(), AllocationError> { 52 if let Some(nptr) = NonNull::new(ptr) { 53 self.zone 54 .deallocate(nptr, layout) 55 .expect("Couldn't deallocate"); 56 return Ok(()); 57 } else { 58 return Ok(()); 59 } 60 } 61 } 62 63 /// 初始化slab分配器 64 pub unsafe fn slab_init() { 65 kdebug!("trying to init a slab_allocator"); 66 SLABALLOCATOR = Some(SlabAllocator::new()); 67 SLABINITSTATE = true.into(); 68 } 69 70 // 查看slab初始化状态 71 pub fn slab_init_state() -> bool { 72 unsafe { *SLABINITSTATE.get_mut() } 73 } 74 75 pub unsafe fn slab_usage() -> SlabUsage { 76 if let Some(ref mut slab) = SLABALLOCATOR { 77 slab.zone.usage() 78 } else { 79 SlabUsage::new(0, 0) 80 } 81 } 82