lib.rs 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #![no_std]
  2. mod free_area;
  3. mod zone;
  4. use core::sync::atomic::Ordering;
  5. use eonix_mm::{
  6. address::PAddr,
  7. paging::{PageAlloc, PageFlags, RawPagePtr, PFN},
  8. };
  9. use eonix_sync::Spin;
  10. use zone::Zone;
  11. pub use free_area::FreeArea;
  12. const MAX_ORDER: u32 = 10;
  13. const ZONE_AREAS: usize = const { MAX_ORDER as usize + 1 };
  14. static BUDDY_ALLOCATOR: BuddyAllocator = BuddyAllocator::new();
  15. pub struct BuddyAllocator {
  16. zone: Spin<Zone<ZONE_AREAS>>,
  17. }
  18. impl BuddyAllocator {
  19. const fn new() -> Self {
  20. Self {
  21. zone: Spin::new(Zone::new()),
  22. }
  23. }
  24. pub fn create_pages(start: PAddr, end: PAddr) {
  25. BUDDY_ALLOCATOR.zone.lock().create_pages(start, end);
  26. }
  27. }
  28. impl PageAlloc for BuddyAllocator {
  29. fn alloc_order(order: u32) -> Option<RawPagePtr> {
  30. let pages_ptr = BUDDY_ALLOCATOR.zone.lock().get_free_pages(order);
  31. if let Some(pages_ptr) = pages_ptr {
  32. // SAFETY: Memory order here can be Relaxed is for the same reason as that
  33. // in the copy constructor of `std::shared_ptr`.
  34. pages_ptr.refcount().fetch_add(1, Ordering::Relaxed);
  35. pages_ptr.flags().clear(PageFlags::FREE);
  36. }
  37. pages_ptr
  38. }
  39. unsafe fn dealloc(page_ptr: RawPagePtr) {
  40. BUDDY_ALLOCATOR.zone.lock().free_pages(page_ptr);
  41. }
  42. unsafe fn has_management_over(page_ptr: RawPagePtr) -> bool {
  43. !page_ptr.flags().has(PageFlags::FREE) && page_ptr.flags().has(PageFlags::BUDDY)
  44. }
  45. }
  46. pub(self) trait BuddyPFNOps {
  47. fn buddy_pfn(self, order: u32) -> PFN;
  48. fn combined_pfn(self, buddy_pfn: PFN) -> PFN;
  49. }
  50. impl BuddyPFNOps for PFN {
  51. fn buddy_pfn(self, order: u32) -> PFN {
  52. PFN::from(usize::from(self) ^ (1 << order))
  53. }
  54. fn combined_pfn(self, buddy_pfn: PFN) -> PFN {
  55. PFN::from(usize::from(self) & usize::from(buddy_pfn))
  56. }
  57. }