1use core::{fmt::Debug, mem::ManuallyDrop, ops::Range};
6
7use super::{
8 Frame, inc_frame_ref_count,
9 meta::{AnyFrameMeta, GetFrameError},
10};
11use crate::mm::{AnyUFrameMeta, HasPaddr, HasSize, PAGE_SIZE, Paddr};
12
13#[repr(transparent)]
26pub struct Segment<M: AnyFrameMeta + ?Sized> {
27 range: Range<Paddr>,
28 _marker: core::marker::PhantomData<M>,
29}
30
31impl<M: AnyFrameMeta + ?Sized> Debug for Segment<M> {
32 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
33 write!(f, "Segment({:#x}..{:#x})", self.range.start, self.range.end)
34 }
35}
36
37pub type USegment = Segment<dyn AnyUFrameMeta>;
45
46impl<M: AnyFrameMeta + ?Sized> Drop for Segment<M> {
47 fn drop(&mut self) {
48 for paddr in self.range.clone().step_by(PAGE_SIZE) {
49 drop(unsafe { Frame::<M>::from_raw(paddr) });
52 }
53 }
54}
55
56impl<M: AnyFrameMeta + ?Sized> Clone for Segment<M> {
57 fn clone(&self) -> Self {
58 for paddr in self.range.clone().step_by(PAGE_SIZE) {
59 unsafe { inc_frame_ref_count(paddr) };
63 }
64 Self {
65 range: self.range.clone(),
66 _marker: core::marker::PhantomData,
67 }
68 }
69}
70
71impl<M: AnyFrameMeta> Segment<M> {
72 pub fn from_unused<F>(range: Range<Paddr>, mut metadata_fn: F) -> Result<Self, GetFrameError>
86 where
87 F: FnMut(Paddr) -> M,
88 {
89 if !range.start.is_multiple_of(PAGE_SIZE) || !range.end.is_multiple_of(PAGE_SIZE) {
90 return Err(GetFrameError::NotAligned);
91 }
92 if range.end > super::max_paddr() {
93 return Err(GetFrameError::OutOfBound);
94 }
95 assert!(range.start < range.end);
96 let mut segment = Self {
99 range: range.start..range.start,
100 _marker: core::marker::PhantomData,
101 };
102 for paddr in range.step_by(PAGE_SIZE) {
103 let frame = Frame::<M>::from_unused(paddr, metadata_fn(paddr))?;
104 let _ = ManuallyDrop::new(frame);
105 segment.range.end = paddr + PAGE_SIZE;
106 }
107 Ok(segment)
108 }
109
110 pub(crate) unsafe fn from_raw(range: Range<Paddr>) -> Self {
118 debug_assert_eq!(range.start % PAGE_SIZE, 0);
119 debug_assert_eq!(range.end % PAGE_SIZE, 0);
120 Self {
121 range,
122 _marker: core::marker::PhantomData,
123 }
124 }
125}
126
127impl<M: AnyFrameMeta + ?Sized> Segment<M> {
128 pub fn split(self, offset: usize) -> (Self, Self) {
138 assert!(offset.is_multiple_of(PAGE_SIZE));
139 assert!(0 < offset && offset < self.size());
140
141 let old = ManuallyDrop::new(self);
142 let at = old.range.start + offset;
143
144 (
145 Self {
146 range: old.range.start..at,
147 _marker: core::marker::PhantomData,
148 },
149 Self {
150 range: at..old.range.end,
151 _marker: core::marker::PhantomData,
152 },
153 )
154 }
155
156 pub fn slice(&self, range: &Range<usize>) -> Self {
166 assert!(range.start.is_multiple_of(PAGE_SIZE) && range.end.is_multiple_of(PAGE_SIZE));
167 let start = self.range.start + range.start;
168 let end = self.range.start + range.end;
169 assert!(start <= end && end <= self.range.end);
170
171 for paddr in (start..end).step_by(PAGE_SIZE) {
172 unsafe { inc_frame_ref_count(paddr) };
176 }
177
178 Self {
179 range: start..end,
180 _marker: core::marker::PhantomData,
181 }
182 }
183
184 pub(crate) fn into_raw(self) -> Range<Paddr> {
186 let range = self.range.clone();
187 let _ = ManuallyDrop::new(self);
188 range
189 }
190}
191
192impl<M: AnyFrameMeta + ?Sized> HasPaddr for Segment<M> {
193 fn paddr(&self) -> Paddr {
194 self.range.start
195 }
196}
197
198impl<M: AnyFrameMeta + ?Sized> HasSize for Segment<M> {
199 fn size(&self) -> usize {
200 self.range.end - self.range.start
201 }
202}
203
204impl<M: AnyFrameMeta + ?Sized> From<Frame<M>> for Segment<M> {
205 fn from(frame: Frame<M>) -> Self {
206 let pa = frame.paddr();
207 let _ = ManuallyDrop::new(frame);
208 Self {
209 range: pa..pa + PAGE_SIZE,
210 _marker: core::marker::PhantomData,
211 }
212 }
213}
214
215impl<M: AnyFrameMeta + ?Sized> Iterator for Segment<M> {
216 type Item = Frame<M>;
217
218 fn next(&mut self) -> Option<Self::Item> {
219 if self.range.start < self.range.end {
220 let frame = unsafe { Frame::<M>::from_raw(self.range.start) };
223 self.range.start += PAGE_SIZE;
224 debug_assert!(self.range.start <= self.range.end);
226 Some(frame)
227 } else {
228 None
229 }
230 }
231}
232
233impl<M: AnyFrameMeta> From<Segment<M>> for Segment<dyn AnyFrameMeta> {
234 fn from(seg: Segment<M>) -> Self {
235 let seg = ManuallyDrop::new(seg);
236 Self {
237 range: seg.range.clone(),
238 _marker: core::marker::PhantomData,
239 }
240 }
241}
242
243impl<M: AnyFrameMeta> TryFrom<Segment<dyn AnyFrameMeta>> for Segment<M> {
244 type Error = Segment<dyn AnyFrameMeta>;
245
246 fn try_from(seg: Segment<dyn AnyFrameMeta>) -> core::result::Result<Self, Self::Error> {
247 let first_frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(seg.range.start) };
250 let first_frame = ManuallyDrop::new(first_frame);
251 if !(first_frame.dyn_meta() as &dyn core::any::Any).is::<M>() {
252 return Err(seg);
253 }
254 #[cfg(debug_assertions)]
257 {
258 for paddr in seg.range.clone().step_by(PAGE_SIZE) {
259 let frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(paddr) };
260 let frame = ManuallyDrop::new(frame);
261 debug_assert!((frame.dyn_meta() as &dyn core::any::Any).is::<M>());
262 }
263 }
264 Ok(unsafe { core::mem::transmute::<Segment<dyn AnyFrameMeta>, Segment<M>>(seg) })
266 }
267}
268
269impl<M: AnyUFrameMeta> From<Segment<M>> for USegment {
270 fn from(seg: Segment<M>) -> Self {
271 unsafe { core::mem::transmute(seg) }
273 }
274}
275
276impl TryFrom<Segment<dyn AnyFrameMeta>> for USegment {
277 type Error = Segment<dyn AnyFrameMeta>;
278
279 fn try_from(seg: Segment<dyn AnyFrameMeta>) -> core::result::Result<Self, Self::Error> {
284 let first_frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(seg.range.start) };
287 let first_frame = ManuallyDrop::new(first_frame);
288 if !first_frame.dyn_meta().is_untyped() {
289 return Err(seg);
290 }
291 #[cfg(debug_assertions)]
294 {
295 for paddr in seg.range.clone().step_by(PAGE_SIZE) {
296 let frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(paddr) };
297 let frame = ManuallyDrop::new(frame);
298 debug_assert!(frame.dyn_meta().is_untyped());
299 }
300 }
301 Ok(unsafe { core::mem::transmute::<Segment<dyn AnyFrameMeta>, USegment>(seg) })
303 }
304}