free_area.rs 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. use core::marker::{Send, Sync};
  2. use eonix_mm::paging::{PageFlags, RawPage, RawPagePtr};
  3. use intrusive_list::{container_of, Link};
  4. pub struct FreeArea {
  5. free_list: Link,
  6. count: usize,
  7. }
  8. unsafe impl Send for FreeArea {}
  9. unsafe impl Sync for FreeArea {}
  10. impl FreeArea {
  11. pub const fn new() -> Self {
  12. Self {
  13. free_list: Link::new(),
  14. count: 0,
  15. }
  16. }
  17. pub fn get_free_pages(&mut self) -> Option<RawPagePtr> {
  18. self.free_list.next_mut().map(|pages_link| {
  19. assert_ne!(self.count, 0);
  20. let pages_ptr = unsafe { container_of!(pages_link, RawPage, link) };
  21. let pages_ptr = RawPagePtr::new(pages_ptr);
  22. self.count -= 1;
  23. pages_link.remove();
  24. pages_ptr
  25. })
  26. }
  27. pub fn add_pages(&mut self, pages_ptr: RawPagePtr) {
  28. self.count += 1;
  29. pages_ptr.as_mut().flags.set(PageFlags::FREE);
  30. self.free_list.insert(&mut pages_ptr.as_mut().link)
  31. }
  32. pub fn del_pages(&mut self, pages_ptr: RawPagePtr) {
  33. assert!(self.count >= 1 && pages_ptr.as_ref().flags.has(PageFlags::FREE));
  34. self.count -= 1;
  35. pages_ptr.as_mut().flags.clear(PageFlags::FREE);
  36. pages_ptr.as_mut().link.remove();
  37. }
  38. }