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