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, Split};
12
13#[repr(transparent)]
31pub struct Segment<M: AnyFrameMeta + ?Sized> {
32 range: Range<Paddr>,
34 _marker: core::marker::PhantomData<M>,
35}
36
37impl<M: AnyFrameMeta + ?Sized> Debug for Segment<M> {
38 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39 write!(f, "Segment({:#x}..{:#x})", self.range.start, self.range.end)
40 }
41}
42
43pub type USegment = Segment<dyn AnyUFrameMeta>;
51
52impl<M: AnyFrameMeta + ?Sized> Drop for Segment<M> {
53 fn drop(&mut self) {
54 unsafe { release_frames::<M>(&self.range) };
57 }
58}
59
60unsafe fn release_frames<M: AnyFrameMeta + ?Sized>(range: &Range<Paddr>) {
65 for paddr in range.clone().step_by(PAGE_SIZE) {
66 drop(unsafe { Frame::<M>::from_raw(paddr) });
68 }
69}
70
71impl<M: AnyFrameMeta + ?Sized> Clone for Segment<M> {
72 fn clone(&self) -> Self {
73 for paddr in self.range.clone().step_by(PAGE_SIZE) {
74 unsafe { inc_frame_ref_count(paddr) };
78 }
79 Self {
80 range: self.range.clone(),
81 _marker: core::marker::PhantomData,
82 }
83 }
84}
85
86impl<M: AnyFrameMeta> Segment<M> {
87 pub fn from_unused<F>(range: Range<Paddr>, mut metadata_fn: F) -> Result<Self, GetFrameError>
101 where
102 F: FnMut(Paddr) -> M,
103 {
104 if !range.start.is_multiple_of(PAGE_SIZE) || !range.end.is_multiple_of(PAGE_SIZE) {
105 return Err(GetFrameError::NotAligned);
106 }
107 if range.end > super::max_paddr() {
108 return Err(GetFrameError::OutOfBound);
109 }
110 assert!(range.start < range.end);
111 let mut paddr_iter = range.step_by(PAGE_SIZE);
112 let mut segment = {
115 let first_paddr = paddr_iter.next().unwrap();
121 Self::from(Frame::<M>::from_unused(
122 first_paddr,
123 metadata_fn(first_paddr),
124 )?)
125 };
126 for paddr in paddr_iter {
127 let frame = Frame::<M>::from_unused(paddr, metadata_fn(paddr))?;
128 let _ = ManuallyDrop::new(frame);
129 segment.range.end = paddr + PAGE_SIZE;
130 }
131 Ok(segment)
132 }
133
134 pub(crate) unsafe fn from_raw(range: Range<Paddr>) -> Self {
145 debug_assert_eq!(range.start % PAGE_SIZE, 0);
146 debug_assert_eq!(range.end % PAGE_SIZE, 0);
147 debug_assert!(range.start < range.end);
148 Self {
149 range,
150 _marker: core::marker::PhantomData,
151 }
152 }
153}
154
155impl<M: AnyFrameMeta + ?Sized> Split for Segment<M> {
156 fn split(self, offset: usize) -> (Self, Self) {
157 assert!(
158 offset.is_multiple_of(PAGE_SIZE),
159 "segment virtual address not aligned for splitting"
160 );
161 assert!(
162 0 < offset && offset < self.size(),
163 "segment virtual address out-of-bound for splitting"
164 );
165
166 let old = ManuallyDrop::new(self);
167 let at = old.range.start + offset;
168
169 (
170 Self {
171 range: old.range.start..at,
172 _marker: core::marker::PhantomData,
173 },
174 Self {
175 range: at..old.range.end,
176 _marker: core::marker::PhantomData,
177 },
178 )
179 }
180}
181
182impl<M: AnyFrameMeta + ?Sized> Segment<M> {
183 pub fn slice(&self, range: &Range<usize>) -> Self {
194 assert!(
195 range.start.is_multiple_of(PAGE_SIZE) && range.end.is_multiple_of(PAGE_SIZE),
196 "segment virtual address not aligned for slicing"
197 );
198 assert!(
199 range.end <= self.size(),
200 "segment virtual address out-of-bound for slicing"
201 );
202 assert!(
203 range.start < range.end,
204 "segment virtual address empty for slicing"
205 );
206
207 let start = self.range.start + range.start;
208 let end = self.range.start + range.end;
209
210 for paddr in (start..end).step_by(PAGE_SIZE) {
211 unsafe { inc_frame_ref_count(paddr) };
215 }
216
217 Self {
218 range: start..end,
219 _marker: core::marker::PhantomData,
220 }
221 }
222
223 pub(crate) fn into_raw(self) -> Range<Paddr> {
225 let range = self.range.clone();
226 let _ = ManuallyDrop::new(self);
227 range
228 }
229}
230
231impl Segment<dyn AnyFrameMeta> {
232 pub fn from_unsized<M: AnyFrameMeta + ?Sized>(
245 segment: Segment<M>,
246 ) -> Segment<dyn AnyFrameMeta> {
247 let seg = ManuallyDrop::new(segment);
248 Self {
249 range: seg.range.clone(),
250 _marker: core::marker::PhantomData,
251 }
252 }
253}
254
255impl<M: AnyFrameMeta + ?Sized> HasPaddr for Segment<M> {
256 fn paddr(&self) -> Paddr {
257 self.range.start
258 }
259}
260
261impl<M: AnyFrameMeta + ?Sized> HasSize for Segment<M> {
262 fn size(&self) -> usize {
263 self.range.end - self.range.start
264 }
265}
266
267impl<M: AnyFrameMeta + ?Sized> From<Frame<M>> for Segment<M> {
268 fn from(frame: Frame<M>) -> Self {
269 let pa = frame.paddr();
270 let _ = ManuallyDrop::new(frame);
271 Self {
272 range: pa..pa + PAGE_SIZE,
273 _marker: core::marker::PhantomData,
274 }
275 }
276}
277
278impl<M: AnyFrameMeta> From<Segment<M>> for Segment<dyn AnyFrameMeta> {
279 fn from(seg: Segment<M>) -> Self {
280 Self::from_unsized(seg)
281 }
282}
283
284impl<M: AnyFrameMeta> TryFrom<Segment<dyn AnyFrameMeta>> for Segment<M> {
285 type Error = Segment<dyn AnyFrameMeta>;
286
287 fn try_from(seg: Segment<dyn AnyFrameMeta>) -> Result<Self, Self::Error> {
288 let first_frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(seg.range.start) };
291 let first_frame = ManuallyDrop::new(first_frame);
292 if !(first_frame.dyn_meta() as &dyn core::any::Any).is::<M>() {
293 return Err(seg);
294 }
295 #[cfg(debug_assertions)]
298 {
299 for paddr in seg.range.clone().step_by(PAGE_SIZE) {
300 let frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(paddr) };
301 let frame = ManuallyDrop::new(frame);
302 debug_assert!((frame.dyn_meta() as &dyn core::any::Any).is::<M>());
303 }
304 }
305 Ok(unsafe { core::mem::transmute::<Segment<dyn AnyFrameMeta>, Segment<M>>(seg) })
307 }
308}
309
310impl<M: AnyUFrameMeta> From<Segment<M>> for USegment {
311 fn from(seg: Segment<M>) -> Self {
312 unsafe { core::mem::transmute(seg) }
314 }
315}
316
317impl TryFrom<Segment<dyn AnyFrameMeta>> for USegment {
318 type Error = Segment<dyn AnyFrameMeta>;
319
320 fn try_from(seg: Segment<dyn AnyFrameMeta>) -> Result<Self, Self::Error> {
325 let first_frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(seg.range.start) };
328 let first_frame = ManuallyDrop::new(first_frame);
329 if !first_frame.dyn_meta().is_untyped() {
330 return Err(seg);
331 }
332 #[cfg(debug_assertions)]
335 {
336 for paddr in seg.range.clone().step_by(PAGE_SIZE) {
337 let frame = unsafe { Frame::<dyn AnyFrameMeta>::from_raw(paddr) };
338 let frame = ManuallyDrop::new(frame);
339 debug_assert!(frame.dyn_meta().is_untyped());
340 }
341 }
342 Ok(unsafe { core::mem::transmute::<Segment<dyn AnyFrameMeta>, USegment>(seg) })
344 }
345}
346
347pub use self::iter::IntoIter;
348
349mod iter {
350 use core::{marker::PhantomData, ops::Range};
351
352 use super::{Frame, Segment};
353 use crate::mm::{PAGE_SIZE, Paddr, frame::meta::AnyFrameMeta};
354
355 pub struct IntoIter<M: AnyFrameMeta + ?Sized> {
361 range: Range<Paddr>,
362 _marker: PhantomData<M>,
363 }
364
365 impl<M: AnyFrameMeta + ?Sized> Iterator for IntoIter<M> {
366 type Item = Frame<M>;
367
368 fn next(&mut self) -> Option<Self::Item> {
369 if self.range.start < self.range.end {
370 let frame = unsafe { Frame::<M>::from_raw(self.range.start) };
373 self.range.start += PAGE_SIZE;
374 debug_assert!(self.range.start <= self.range.end);
376 Some(frame)
377 } else {
378 None
379 }
380 }
381 }
382
383 impl<M: AnyFrameMeta + ?Sized> Drop for IntoIter<M> {
384 fn drop(&mut self) {
385 unsafe { super::release_frames::<M>(&self.range) };
388 }
389 }
390
391 impl<M: AnyFrameMeta + ?Sized> IntoIterator for Segment<M> {
392 type Item = Frame<M>;
393 type IntoIter = IntoIter<M>;
394
395 fn into_iter(self) -> Self::IntoIter {
396 IntoIter {
397 range: self.into_raw(),
398 _marker: PhantomData,
399 }
400 }
401 }
402}