free_area.rs 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. use crate::BuddyRawPage;
  2. use core::marker::{PhantomData, Send, Sync};
  3. use intrusive_list::Link;
  4. pub struct FreeArea<T> {
  5. free_list: Link,
  6. count: usize,
  7. _phantom: PhantomData<T>,
  8. }
  9. unsafe impl<T> Send for FreeArea<T> {}
  10. unsafe impl<T> Sync for FreeArea<T> {}
  11. impl<Raw> FreeArea<Raw>
  12. where
  13. Raw: BuddyRawPage,
  14. {
  15. pub const fn new() -> Self {
  16. Self {
  17. free_list: Link::new(),
  18. count: 0,
  19. _phantom: PhantomData,
  20. }
  21. }
  22. pub fn get_free_pages(&mut self) -> Option<Raw> {
  23. self.free_list.next_mut().map(|pages_link| {
  24. assert_ne!(self.count, 0);
  25. let pages_ptr = unsafe {
  26. // SAFETY: Items in `self.free_list` are guaranteed to be of type `Raw`.
  27. Raw::from_link(pages_link)
  28. };
  29. self.count -= 1;
  30. pages_link.remove();
  31. pages_ptr
  32. })
  33. }
  34. pub fn add_pages(&mut self, pages_ptr: Raw) {
  35. self.count += 1;
  36. pages_ptr.set_free();
  37. unsafe {
  38. self.free_list.insert(pages_ptr.get_link());
  39. }
  40. }
  41. pub fn del_pages(&mut self, pages_ptr: Raw) {
  42. assert!(self.count >= 1 && pages_ptr.is_free());
  43. self.count -= 1;
  44. pages_ptr.clear_free();
  45. unsafe {
  46. pages_ptr.get_link().remove();
  47. }
  48. }
  49. }