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