diff --git a/ostd/src/mm/page_table/cursor.rs b/ostd/src/mm/page_table/cursor.rs index e8ec0f2e1..7f3c49a70 100644 --- a/ostd/src/mm/page_table/cursor.rs +++ b/ostd/src/mm/page_table/cursor.rs @@ -45,10 +45,25 @@ //! 5. Map some pages in D; //! 6. `unlock(D)`, `lock_guard = [ locked(B) ]`; //! -//! If all the mappings in `B` are cancelled when cursor finished it's traversal, -//! and `B` need to be recycled, a page walk from the root page table to `B` is -//! required. The cursor unlock all locks, then lock all the way down to `B`, then -//! check if `B` is empty, and finally recycle all the resources on the way back. +//! +//! ## Validity +//! +//! The page table cursor API will guarentee that the page table, as a data +//! structure, whose occupied memory will not suffer from data races. This is +//! ensured by the page table lock protocol. In other words, any operations +//! provided by the APIs (as long as safety requirements are met) will not +//! break the page table data structure (or other memory). +//! +//! However, the page table cursor creation APIs, [`CursorMut::new`] or +//! [`Cursor::new`], do not guarantee exclusive access to the virtual address +//! area you claim. From the lock protocol, you can see that there are chances +//! to create 2 cursors that claim the same virtual address range (one covers +//! another). In this case, the greater cursor may block if it wants to modify +//! the page table entries covered by the smaller cursor. Also, if the greater +//! cursor destructs the smaller cursor's parent page table node, it won't block +//! and the smaller cursor's change will not be visible. The user of the page +//! table cursor should add additional entry point checks to prevent these defined +//! behaviors if they are not wanted. use core::{any::TypeId, marker::PhantomData, ops::Range}; @@ -106,10 +121,14 @@ impl<'a, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait> Cursor< where [(); C::NR_LEVELS as usize]:, { - /// Creates a cursor exclusively owning the locks for the given range. + /// Creates a cursor claiming the read access for the given range. /// - /// The cursor created will only be able to map, query or jump within the - /// given range. + /// The cursor created will only be able to query or jump within the given + /// range. Out-of-bound accesses will result in panics or errors as return values, + /// depending on the access method. + /// + /// Note that this function does not ensure exclusive access to the claimed + /// virtual address range. The accesses using this cursor may block or fail. pub(crate) fn new( pt: &'a PageTable, va: &Range, @@ -317,6 +336,15 @@ impl<'a, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait> CursorM where [(); C::NR_LEVELS as usize]:, { + /// Creates a cursor claiming the write access for the given range. + /// + /// The cursor created will only be able to map, query or jump within the given + /// range. Out-of-bound accesses will result in panics or errors as return values, + /// depending on the access method. + /// + /// Note that this function, the same as [`Cursor::new`], does not ensure exclusive + /// access to the claimed virtual address range. The accesses using this cursor may + /// block or fail. pub(super) fn new( pt: &'a PageTable, va: &Range,