hermit/mm/
page_range_alloc.rs

1use core::alloc::AllocError;
2use core::marker::PhantomData;
3use core::mem::ManuallyDrop;
4use core::ops::Deref;
5
6use free_list::{PageLayout, PageRange};
7
8/// An allocator that allocates memory in page granularity.
9pub trait PageRangeAllocator {
10	unsafe fn init();
11
12	/// Attempts to allocate a range of memory in page granularity.
13	fn allocate(layout: PageLayout) -> Result<PageRange, AllocError>;
14
15	/// Attempts to allocate the pages described by `range`.
16	fn allocate_at(range: PageRange) -> Result<(), AllocError>;
17
18	/// Deallocates the pages described by `range`.
19	///
20	/// # Safety
21	///
22	/// - `range` must described a range of pages _currently allocated_ via this allocator.
23	unsafe fn deallocate(range: PageRange);
24}
25
26pub struct PageRangeBox<A: PageRangeAllocator>(PageRange, PhantomData<A>);
27
28impl<A: PageRangeAllocator> PageRangeBox<A> {
29	pub fn new(layout: PageLayout) -> Result<Self, AllocError> {
30		let range = A::allocate(layout)?;
31		Ok(Self(range, PhantomData))
32	}
33
34	pub unsafe fn from_raw(range: PageRange) -> Self {
35		Self(range, PhantomData)
36	}
37
38	pub fn into_raw(b: Self) -> PageRange {
39		let b = ManuallyDrop::new(b);
40		**b
41	}
42}
43
44impl<A: PageRangeAllocator> Drop for PageRangeBox<A> {
45	fn drop(&mut self) {
46		unsafe {
47			A::deallocate(self.0);
48		}
49	}
50}
51
52impl<A: PageRangeAllocator> Deref for PageRangeBox<A> {
53	type Target = PageRange;
54
55	fn deref(&self) -> &Self::Target {
56		&self.0
57	}
58}