xref: /DragonOS/kernel/crates/rust-slabmalloc/src/lib.rs (revision ceeb2e943ca7645609920ec7ad8bfceea2b13de6)
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