From 71a486b9a5627255468b7b934c9d0ce466eec056 Mon Sep 17 00:00:00 2001 From: Zhang Junyang Date: Thu, 4 Jul 2024 15:07:51 +0000 Subject: [PATCH] Bye, `FrameVec` --- ostd/src/mm/frame/frame_vec.rs | 172 --------------------------------- ostd/src/mm/frame/mod.rs | 44 ++++++++- ostd/src/mm/frame/options.rs | 6 +- ostd/src/mm/frame/segment.rs | 5 - ostd/src/mm/io.rs | 5 +- ostd/src/mm/mod.rs | 2 +- 6 files changed, 48 insertions(+), 186 deletions(-) delete mode 100644 ostd/src/mm/frame/frame_vec.rs diff --git a/ostd/src/mm/frame/frame_vec.rs b/ostd/src/mm/frame/frame_vec.rs deleted file mode 100644 index e37e84e56..000000000 --- a/ostd/src/mm/frame/frame_vec.rs +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Page frames. - -use alloc::{vec, vec::Vec}; - -use crate::{ - mm::{Frame, VmIo, VmReader, VmWriter, PAGE_SIZE}, - Error, Result, -}; - -/// A collection of base page frames (regular physical memory pages). -/// -/// For the most parts, `FrameVec` is like `Vec`. But the -/// implementation may or may not be based on [`Vec`]. Having a dedicated -/// type to represent a series of page frames is convenient because, -/// more often than not, one needs to operate on a batch of frames rather -/// a single frame. -#[derive(Debug, Clone)] -pub struct FrameVec(pub(crate) Vec); - -impl FrameVec { - /// Retrieves a reference to a [`Frame`] at the specified index. - pub fn get(&self, index: usize) -> Option<&Frame> { - self.0.get(index) - } - - /// Creates an empty `FrameVec`. - pub fn empty() -> Self { - Self(Vec::new()) - } - - /// Creates a new `FrameVec` with the specified capacity. - pub fn new_with_capacity(capacity: usize) -> Self { - Self(Vec::with_capacity(capacity)) - } - - /// Pushes a new frame to the collection. - pub fn push(&mut self, new_frame: Frame) { - self.0.push(new_frame); - } - - /// Pops a frame from the collection. - pub fn pop(&mut self) -> Option { - self.0.pop() - } - - /// Removes a frame at a position. - pub fn remove(&mut self, at: usize) -> Frame { - self.0.remove(at) - } - - /// Appends all the [`Frame`]s from `more` to the end of this collection. - /// and clears the frames in `more`. - pub fn append(&mut self, more: &mut FrameVec) -> Result<()> { - self.0.append(&mut more.0); - Ok(()) - } - - /// Truncates the `FrameVec` to the specified length. - /// - /// If `new_len >= self.len()`, then this method has no effect. - pub fn truncate(&mut self, new_len: usize) { - if new_len >= self.0.len() { - return; - } - self.0.truncate(new_len) - } - - /// Returns an iterator over all frames. - pub fn iter(&self) -> core::slice::Iter<'_, Frame> { - self.0.iter() - } - - /// Returns the number of frames. - pub fn len(&self) -> usize { - self.0.len() - } - - /// Returns whether the frame collection is empty. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Returns the number of bytes. - /// - /// This method is equivalent to `self.len() * BASE_PAGE_SIZE`. - pub fn nbytes(&self) -> usize { - self.0.len() * PAGE_SIZE - } - - /// Creates a new `FrameVec` from a single [`Frame`]. - pub fn from_one_frame(frame: Frame) -> Self { - Self(vec![frame]) - } -} - -impl IntoIterator for FrameVec { - type Item = Frame; - - type IntoIter = alloc::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl VmIo for FrameVec { - fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> { - // Do bound check with potential integer overflow in mind - let max_offset = offset.checked_add(buf.len()).ok_or(Error::Overflow)?; - if max_offset > self.nbytes() { - return Err(Error::InvalidArgs); - } - - let num_unread_pages = offset / PAGE_SIZE; - let mut start = offset % PAGE_SIZE; - let mut buf_writer: VmWriter = buf.into(); - for frame in self.0.iter().skip(num_unread_pages) { - let read_len = frame.reader().skip(start).read(&mut buf_writer); - if read_len == 0 { - break; - } - start = 0; - } - Ok(()) - } - - fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()> { - // Do bound check with potential integer overflow in mind - let max_offset = offset.checked_add(buf.len()).ok_or(Error::Overflow)?; - if max_offset > self.nbytes() { - return Err(Error::InvalidArgs); - } - - let num_unwrite_pages = offset / PAGE_SIZE; - let mut start = offset % PAGE_SIZE; - let mut buf_reader: VmReader = buf.into(); - for frame in self.0.iter().skip(num_unwrite_pages) { - let write_len = frame.writer().skip(start).write(&mut buf_reader); - if write_len == 0 { - break; - } - start = 0; - } - Ok(()) - } -} - -/// An iterator for frames. -pub struct FrameVecIter<'a> { - frames: &'a FrameVec, - current: usize, -} - -impl<'a> FrameVecIter<'a> { - /// Creates a new `FrameVecIter` from the given [`FrameVec`]. - pub fn new(frames: &'a FrameVec) -> Self { - Self { frames, current: 0 } - } -} - -impl<'a> Iterator for FrameVecIter<'a> { - type Item = &'a Frame; - - fn next(&mut self) -> Option { - if self.current >= self.frames.0.len() { - return None; - } - Some(self.frames.0.get(self.current).unwrap()) - } -} diff --git a/ostd/src/mm/frame/mod.rs b/ostd/src/mm/frame/mod.rs index 62a035288..6a880af26 100644 --- a/ostd/src/mm/frame/mod.rs +++ b/ostd/src/mm/frame/mod.rs @@ -8,13 +8,11 @@ //! frames. Frames, with all the properties of pages, can additionally be safely //! read and written by the kernel or the user. -pub mod frame_vec; pub mod options; pub mod segment; use core::mem::ManuallyDrop; -pub use frame_vec::{FrameVec, FrameVecIter}; pub use segment::Segment; use super::page::{ @@ -155,6 +153,48 @@ impl VmIo for Frame { } } +impl VmIo for alloc::vec::Vec { + fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> { + // Do bound check with potential integer overflow in mind + let max_offset = offset.checked_add(buf.len()).ok_or(Error::Overflow)?; + if max_offset > self.len() * PAGE_SIZE { + return Err(Error::InvalidArgs); + } + + let num_skip_pages = offset / PAGE_SIZE; + let mut start = offset % PAGE_SIZE; + let mut buf_writer: VmWriter = buf.into(); + for frame in self.iter().skip(num_skip_pages) { + let read_len = frame.reader().skip(start).read(&mut buf_writer); + if read_len == 0 { + break; + } + start = 0; + } + Ok(()) + } + + fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()> { + // Do bound check with potential integer overflow in mind + let max_offset = offset.checked_add(buf.len()).ok_or(Error::Overflow)?; + if max_offset > self.len() * PAGE_SIZE { + return Err(Error::InvalidArgs); + } + + let num_skip_pages = offset / PAGE_SIZE; + let mut start = offset % PAGE_SIZE; + let mut buf_reader: VmReader = buf.into(); + for frame in self.iter().skip(num_skip_pages) { + let write_len = frame.writer().skip(start).write(&mut buf_reader); + if write_len == 0 { + break; + } + start = 0; + } + Ok(()) + } +} + impl PageMeta for FrameMeta { const USAGE: PageUsage = PageUsage::Frame; diff --git a/ostd/src/mm/frame/options.rs b/ostd/src/mm/frame/options.rs index a5006a6ba..4bd3f627b 100644 --- a/ostd/src/mm/frame/options.rs +++ b/ostd/src/mm/frame/options.rs @@ -2,7 +2,7 @@ //! Options for allocating frames -use super::{Frame, FrameVec, Segment}; +use super::{Frame, Segment}; use crate::{ mm::{ page::{self, meta::FrameMeta}, @@ -55,7 +55,7 @@ impl FrameAllocOptions { } /// Allocates a collection of page frames according to the given options. - pub fn alloc(&self) -> Result { + pub fn alloc(&self) -> Result> { let pages = if self.is_contiguous { page::allocator::alloc(self.nframes * PAGE_SIZE).ok_or(Error::NoMemory)? } else { @@ -63,7 +63,7 @@ impl FrameAllocOptions { .ok_or(Error::NoMemory)? .into() }; - let frames = FrameVec(pages.into_iter().map(|page| Frame { page }).collect()); + let frames: Vec<_> = pages.into_iter().map(|page| Frame { page }).collect(); if !self.uninit { for frame in frames.iter() { frame.writer().fill(0); diff --git a/ostd/src/mm/frame/segment.rs b/ostd/src/mm/frame/segment.rs index aeab21d26..d93adc33e 100644 --- a/ostd/src/mm/frame/segment.rs +++ b/ostd/src/mm/frame/segment.rs @@ -16,15 +16,10 @@ use crate::{ /// A handle to a contiguous range of page frames (physical memory pages). /// -/// The biggest difference between `Segment` and [`FrameVec`] is that -/// the page frames must be contiguous for `Segment`. -/// /// A cloned `Segment` refers to the same page frames as the original. /// As the original and cloned instances point to the same physical address, /// they are treated as equal to each other. /// -/// [`FrameVec`]: crate::mm::FrameVec -/// /// #Example /// /// ```rust diff --git a/ostd/src/mm/io.rs b/ostd/src/mm/io.rs index e923f5d02..d3dcd60d6 100644 --- a/ostd/src/mm/io.rs +++ b/ostd/src/mm/io.rs @@ -18,7 +18,7 @@ use crate::{ }; /// A trait that enables reading/writing data from/to a VM object, -/// e.g., [`VmSpace`], [`FrameVec`], and [`Frame`]. +/// e.g., [`Segment`], [`Vec`] and [`Frame`]. /// /// # Concurrency /// @@ -27,8 +27,7 @@ use crate::{ /// desire predictability or atomicity, the users should add extra mechanism /// for such properties. /// -/// [`VmSpace`]: crate::mm::VmSpace -/// [`FrameVec`]: crate::mm::FrameVec +/// [`Segment`]: crate::mm::Segment /// [`Frame`]: crate::mm::Frame pub trait VmIo: Send + Sync { /// Reads a specified number of bytes at a specified offset into a given buffer. diff --git a/ostd/src/mm/mod.rs b/ostd/src/mm/mod.rs index c1ecdfb18..3d6485ae1 100644 --- a/ostd/src/mm/mod.rs +++ b/ostd/src/mm/mod.rs @@ -26,7 +26,7 @@ use spin::Once; pub use self::{ dma::{Daddr, DmaCoherent, DmaDirection, DmaStream, DmaStreamSlice, HasDaddr}, - frame::{options::FrameAllocOptions, Frame, FrameVec, FrameVecIter, Segment}, + frame::{options::FrameAllocOptions, Frame, Segment}, io::{KernelSpace, UserSpace, VmIo, VmReader, VmWriter}, page_prop::{CachePolicy, PageFlags, PageProperty}, vm_space::VmSpace,