|  | @@ -59,21 +59,29 @@ pub struct SCAllocator<'a, P: AllocablePage> {
 | 
	
		
			
				|  |  |      pub(crate) slabs: PageList<'a, P>,
 | 
	
		
			
				|  |  |      /// List of full ObjectPages (everything allocated in these don't need to search them).
 | 
	
		
			
				|  |  |      pub(crate) full_slabs: PageList<'a, P>,
 | 
	
		
			
				|  |  | +    /// Free objects count
 | 
	
		
			
				|  |  | +    pub(crate) free_obj_count: usize,
 | 
	
		
			
				|  |  | +    /// Maximum free objects num for this `SCAllocator`.
 | 
	
		
			
				|  |  | +    pub(crate) free_limit: usize,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Creates an instance of a scallocator, we do this in a macro because we
 | 
	
		
			
				|  |  |  /// re-use the code in const and non-const functions
 | 
	
		
			
				|  |  |  macro_rules! new_sc_allocator {
 | 
	
		
			
				|  |  | -    ($size:expr) => {
 | 
	
		
			
				|  |  | +    ($size:expr) => {{
 | 
	
		
			
				|  |  | +        let obj_per_page = cmin((P::SIZE - OBJECT_PAGE_METADATA_OVERHEAD) / $size, 8 * 64);
 | 
	
		
			
				|  |  |          SCAllocator {
 | 
	
		
			
				|  |  |              size: $size,
 | 
	
		
			
				|  |  |              allocation_count: 0,
 | 
	
		
			
				|  |  | -            obj_per_page: cmin((P::SIZE - OBJECT_PAGE_METADATA_OVERHEAD) / $size, 8 * 64),
 | 
	
		
			
				|  |  | +            obj_per_page,
 | 
	
		
			
				|  |  |              empty_slabs: PageList::new(),
 | 
	
		
			
				|  |  |              slabs: PageList::new(),
 | 
	
		
			
				|  |  |              full_slabs: PageList::new(),
 | 
	
		
			
				|  |  | +            // TODO: 优化free_limit的计算: https://bbs.dragonos.org.cn/t/topic/358
 | 
	
		
			
				|  |  | +            free_limit: 2 * obj_per_page,
 | 
	
		
			
				|  |  | +            free_obj_count: 0,
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +    }};
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  impl<'a, P: AllocablePage> SCAllocator<'a, P> {
 | 
	
	
		
			
				|  | @@ -241,6 +249,7 @@ impl<'a, P: AllocablePage> SCAllocator<'a, P> {
 | 
	
		
			
				|  |  |          *page.next() = Rawlink::none();
 | 
	
		
			
				|  |  |          trace!("adding page to SCAllocator {:p}", page);
 | 
	
		
			
				|  |  |          self.insert_empty(page);
 | 
	
		
			
				|  |  | +        self.free_obj_count += self.obj_per_page;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /// Allocates a block of memory descriped by `layout`.
 | 
	
	
		
			
				|  | @@ -294,6 +303,7 @@ impl<'a, P: AllocablePage> SCAllocator<'a, P> {
 | 
	
		
			
				|  |  |                  self.size,
 | 
	
		
			
				|  |  |                  ptr as usize
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  | +            self.free_obj_count -= 1;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          res
 | 
	
	
		
			
				|  | @@ -304,7 +314,12 @@ impl<'a, P: AllocablePage> SCAllocator<'a, P> {
 | 
	
		
			
				|  |  |      /// May return an error in case an invalid `layout` is provided.
 | 
	
		
			
				|  |  |      /// The function may also move internal slab pages between lists partial -> empty
 | 
	
		
			
				|  |  |      /// or full -> partial lists.
 | 
	
		
			
				|  |  | -    pub fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) -> Result<(), AllocationError> {
 | 
	
		
			
				|  |  | +    pub unsafe fn deallocate(
 | 
	
		
			
				|  |  | +        &mut self,
 | 
	
		
			
				|  |  | +        ptr: NonNull<u8>,
 | 
	
		
			
				|  |  | +        layout: Layout,
 | 
	
		
			
				|  |  | +        slab_callback: &'static dyn CallBack,
 | 
	
		
			
				|  |  | +    ) -> Result<(), AllocationError> {
 | 
	
		
			
				|  |  |          assert!(layout.size() <= self.size);
 | 
	
		
			
				|  |  |          assert!(self.size <= (P::SIZE - OBJECT_PAGE_METADATA_OVERHEAD));
 | 
	
		
			
				|  |  |          trace!(
 | 
	
	
		
			
				|  | @@ -324,6 +339,17 @@ impl<'a, P: AllocablePage> SCAllocator<'a, P> {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          let ret = slab_page.deallocate(ptr, new_layout);
 | 
	
		
			
				|  |  |          debug_assert!(ret.is_ok(), "Slab page deallocate won't fail at the moment");
 | 
	
		
			
				|  |  | +        self.free_obj_count += 1;
 | 
	
		
			
				|  |  | +        let is_empty_after_dealloc = slab_page.is_empty(self.obj_per_page);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 如果slab_page是空白的,且空闲块数大于free_limit,将slab_page归还buddy
 | 
	
		
			
				|  |  | +        if self.free_obj_count >= self.free_limit && is_empty_after_dealloc {
 | 
	
		
			
				|  |  | +            self.slabs.remove_from_list(slab_page);
 | 
	
		
			
				|  |  | +            // 将slab_page归还buddy
 | 
	
		
			
				|  |  | +            slab_callback.free_slab_page(slab_page as *const P as *mut u8, P::SIZE);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        self.check_page_assignments();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          ret
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |