lib.rs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #![no_std]
  2. mod slab_cache;
  3. use core::cmp::max;
  4. use eonix_mm::paging::{PageAlloc, RawPage};
  5. use eonix_sync::Spin;
  6. use intrusive_list::Link;
  7. use slab_cache::SlabCache;
  8. pub trait SlabRawPage: RawPage {
  9. /// Get the container raw page struct of the list link.
  10. ///
  11. /// # Safety
  12. /// The caller MUST ensure that the link points to a `RawPage`.
  13. unsafe fn from_link(link: &mut Link) -> Self;
  14. /// Get the list link of the raw page.
  15. ///
  16. /// # Safety
  17. /// The caller MUST ensure that at any time, only one mutable reference
  18. /// to the link exists.
  19. unsafe fn get_link(&self) -> &mut Link;
  20. fn slab_init(&self, object_size: u32);
  21. fn is_emtpy(&self) -> bool;
  22. fn is_full(&self) -> bool;
  23. // which slab page the ptr belong
  24. fn in_which(ptr: *mut u8) -> Self;
  25. fn alloc_slot(&self) -> *mut u8;
  26. fn dealloc_slot(&self, ptr: *mut u8);
  27. }
  28. pub struct SlabAllocator<T, A, const SLAB_CACHE_COUNT: usize> {
  29. slabs: [Spin<SlabCache<T, A>>; SLAB_CACHE_COUNT],
  30. }
  31. unsafe impl<T, A, const SLAB_CACHE_COUNT: usize> Send for SlabAllocator<T, A, SLAB_CACHE_COUNT> {}
  32. unsafe impl<T, A, const SLAB_CACHE_COUNT: usize> Sync for SlabAllocator<T, A, SLAB_CACHE_COUNT> {}
  33. impl<Raw, Allocator, const SLAB_CACHE_COUNT: usize> SlabAllocator<Raw, Allocator, SLAB_CACHE_COUNT>
  34. where
  35. Raw: SlabRawPage,
  36. Allocator: PageAlloc<RawPage = Raw> + Clone,
  37. {
  38. pub fn new_in(alloc: Allocator) -> Self {
  39. Self {
  40. slabs: core::array::from_fn(|i| {
  41. Spin::new(SlabCache::new_in(1 << (i + 3), alloc.clone()))
  42. }),
  43. }
  44. }
  45. pub fn alloc(&self, mut size: usize) -> *mut u8 {
  46. size = max(8, size);
  47. let idx = size.next_power_of_two().trailing_zeros() - 3;
  48. self.slabs[idx as usize].lock().alloc()
  49. }
  50. pub fn dealloc(&self, ptr: *mut u8, mut size: usize) {
  51. size = max(8, size);
  52. let idx = size.next_power_of_two().trailing_zeros() - 3;
  53. self.slabs[idx as usize].lock().dealloc(ptr);
  54. }
  55. }