1 //! A slab allocator implementation for objects less than a page-size (4 KiB or 2MiB). 2 //! 3 //! # Overview 4 //! 5 //! The organization is as follows: 6 //! 7 //! * A `ZoneAllocator` manages many `SCAllocator` and can 8 //! satisfy requests for different allocation sizes. 9 //! * A `SCAllocator` allocates objects of exactly one size. 10 //! It stores the objects and meta-data in one or multiple `AllocablePage` objects. 11 //! * A trait `AllocablePage` that defines the page-type from which we allocate objects. 12 //! 13 //! Lastly, it provides two default `AllocablePage` implementations `ObjectPage` and `LargeObjectPage`: 14 //! * A `ObjectPage` that is 4 KiB in size and contains allocated objects and associated meta-data. 15 //! * A `LargeObjectPage` that is 2 MiB in size and contains allocated objects and associated meta-data. 16 //! 17 //! 18 //! # Implementing GlobalAlloc 19 //! See the [global alloc](https://github.com/gz/rust-slabmalloc/tree/master/examples/global_alloc.rs) example. 20 #![allow(unused_features)] 21 #![no_std] 22 #![crate_name = "slabmalloc"] 23 #![crate_type = "lib"] 24 #![feature(maybe_uninit_as_bytes)] 25 26 extern crate alloc; 27 28 mod pages; 29 mod sc; 30 mod zone; 31 32 pub use pages::*; 33 pub use sc::*; 34 pub use zone::*; 35 36 use core::alloc::Layout; 37 use core::fmt; 38 use core::ptr::{self, NonNull}; 39 40 use log::trace; 41 42 /// How many bytes in the page are used by allocator meta-data. 43 const OBJECT_PAGE_METADATA_OVERHEAD: usize = 80; 44 45 /// How many bytes a [`ObjectPage`] is. 46 const OBJECT_PAGE_SIZE: usize = 4096; 47 48 type VAddr = usize; 49 50 /// Error that can be returned for `allocation` and `deallocation` requests. 51 #[derive(Debug)] 52 pub enum AllocationError { 53 /// Can't satisfy the allocation request for Layout because the allocator 54 /// does not have enough memory (you may be able to `refill` it). 55 OutOfMemory, 56 /// Allocator can't deal with the provided size of the Layout. 57 InvalidLayout, 58 } 59 60 /// Allocator trait to be implemented by users of slabmalloc to provide memory to slabmalloc. 61 /// 62 /// # Safety 63 /// Needs to adhere to safety requirements of a rust allocator (see GlobalAlloc et. al.). 64 pub unsafe trait Allocator<'a> { allocate(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocationError>65 fn allocate(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocationError>; 66 /// # Safety 67 /// The caller must ensure that the memory is valid and that the layout is correct. deallocate( &mut self, ptr: NonNull<u8>, layout: Layout, slab_callback: &'static dyn CallBack, ) -> Result<(), AllocationError>68 unsafe fn deallocate( 69 &mut self, 70 ptr: NonNull<u8>, 71 layout: Layout, 72 slab_callback: &'static dyn CallBack, 73 ) -> Result<(), AllocationError>; 74 75 /// Refill the allocator with a [`ObjectPage`]. 76 /// 77 /// # Safety 78 /// TBD (this API needs to change anyways, likely new page should be a raw pointer) refill( &mut self, layout: Layout, new_page: &'a mut ObjectPage<'a>, ) -> Result<(), AllocationError>79 unsafe fn refill( 80 &mut self, 81 layout: Layout, 82 new_page: &'a mut ObjectPage<'a>, 83 ) -> Result<(), AllocationError>; 84 } 85 86 /// 将slab_page归还Buddy的回调函数 87 pub trait CallBack: Send + Sync { 88 /// # Safety 89 /// The caller must ensure that the memory is valid and that the size is correct. free_slab_page(&self, _: *mut u8, _: usize)90 unsafe fn free_slab_page(&self, _: *mut u8, _: usize) {} 91 } 92