Skip to main content

Cursor

Struct Cursor 

Source
pub struct Cursor<'a, A: InAtomicMode>(pub Cursor<'a, UserPtConfig, A>);
Expand description

The cursor for querying over the VM space without modifying it.

It exclusively owns a sub-tree of the page table, preventing others from reading or modifying the same sub-tree. Two read-only cursors can not be created from the same virtual address range either.

Tuple Fields§

§0: Cursor<'a, UserPtConfig, A>

Implementations§

Source§

impl<'rcu, A: InAtomicMode> Cursor<'rcu, A>

Source

pub open spec fn query_success_requires(self) -> bool

{ self.0.barrier_va.start <= self.0.va < self.0.barrier_va.end }
Source

pub open spec fn query_success_ensures( self, view: CursorView<UserPtConfig>, range: Range<Vaddr>, item: Option<MappedItem>, ) -> bool

{
    if view.present() {
        &&& item is Some
        &&& view.query_item_spec(item->0) == Some(range)

    } else {
        &&& range.start == self.0.va
        &&& item is None

    }
}
Source§

impl<'rcu, A: InAtomicMode> Cursor<'rcu, A>

Source

pub exec fn query(&mut self) -> r : Result<(Range<Vaddr>, Option<MappedItem>), Error>

with
Tracked(owner): Tracked<&mut CursorOwner<'rcu, UserPtConfig>>,
Tracked(regions): Tracked<&mut MetaRegionOwners>,
Tracked(guards): Tracked<&mut Guards>,
requires
old(self).0.invariants(*old(owner), *old(regions), *old(guards)),
old(self).0.query_panic_condition(*old(owner), *old(regions)) ==> may_panic(),
ensures
final(self).0.invariants(*final(owner), *final(regions), *final(guards)),
!old(self).0.query_panic_condition(*old(owner), *old(regions)),
old(owner).in_locked_range() ==> r is Ok,
r matches Ok(
    state,
) ==> final(self).0.query_some_condition(*final(owner))
    ==> final(self).0.query_some_ensures(*final(owner), state),
r matches Ok(
    state,
) ==> !final(self).0.query_some_condition(*final(owner))
    ==> final(self).0.query_none_ensures(*final(owner), state),
old(owner)@.mappings == final(owner)@.mappings,

Queries the mapping at the current virtual address.

If the cursor is pointing to a valid virtual address that is locked, it will return the virtual address range and the mapped item.

§Preconditions
  • All system invariants must hold
  • Liveness: The function will return an error if the cursor is not within the locked range
§Postconditions
  • If there is a mapped item at the current virtual address ([query_some_condition]), it is returned along with the virtual address range that it maps ([query_success_ensures]).
  • The mapping that is returned corresponds to the abstract mapping given by query_item_spec.
  • If there is no mapped item at the current virtual address ([query_none_condition]), it returns None, and the virtual address range of the cursor’s current position.
§Safety
  • This function preserves all memory invariants.
  • The locking mechanism prevents data races.
Source

pub exec fn find_next(&mut self, len: usize) -> res : Option<Vaddr>

with
Tracked(owner): Tracked<&mut CursorOwner<'rcu, UserPtConfig>>,
Tracked(regions): Tracked<&mut MetaRegionOwners>,
Tracked(guards): Tracked<&mut Guards>,
requires
old(self).0.invariants(*old(owner), *old(regions), *old(guards)),
old(self).0.find_next_panic_condition(len) ==> may_panic(),
ensures
!old(self).0.find_next_panic_condition(len),
final(self).0.invariants(*final(owner), *final(regions), *final(guards)),
res is Some
    ==> {
        &&& res->0 == final(self).0.va
        &&& final(owner).level <= final(owner).guard_level
        &&& final(owner).in_locked_range()

    },

Moves the cursor forward to the next mapped virtual address.

If there is mapped virtual address following the current address within next len bytes, it will return that mapped address. In this case, the cursor will stop at the mapped address.

Otherwise, it will return None. And the cursor may stop at any address after len bytes.

§Verified Properties
§Preconditions
  • Safety Invariants: The page table cursor safety invariants ([crate::mm::page_table::Cursor::invariants]) must hold before the call.
  • Liveness: In order to avoid a panic, the length must be page-aligned and less than or equal to the remaining range of the cursor.
§Postconditions
  • Safety Invariants: Page table cursor safety invariants are preserved.
  • Correctness: If there is a mapped address after the current address within the next len bytes, it will move the cursor to the next mapped address and return it.
  • Correctness: If the metadata region was well-formed before the call, it will be well-formed after.
§Panics

This method panics if the length is longer than the remaining range of the cursor.

§Safety

This function preserves all memory invariants. Because it panics rather than move the cursor to an invalid address, it ensures that the cursor is safe to use after the call.

Source

pub exec fn jump(&mut self, va: Vaddr) -> res : Result<(), Error>

with
Tracked(owner): Tracked<&mut CursorOwner<'rcu, UserPtConfig>>,
Tracked(regions): Tracked<&mut MetaRegionOwners>,
Tracked(guards): Tracked<&mut Guards>,
requires
old(self).0.invariants(*old(owner), *old(regions), *old(guards)),
old(self).0.jump_panic_condition(va) ==> may_panic(),
ensures
!old(self).0.jump_panic_condition(va),
final(self).0.invariants(*final(owner), *final(regions), *final(guards)),
final(self).0.barrier_va.start <= va < final(self).0.barrier_va.end
    ==> {
        &&& res is Ok
        &&& final(self).0.va == va

    },
!(final(self).0.barrier_va.start <= va < final(self).0.barrier_va.end) ==> res is Err,

Jumps to the virtual address.

If the target address is out of the range, this method will return Err.

§Panics

This method panics if the address has bad alignment.

§Verified Properties
§Preconditions
  • Safety Invariants: The page table cursor safety invariants ([crate::mm::page_table::Cursor::invariants]) must hold before the call.
  • Liveness: The function will panic if the target va is not aligned to the base page size.
§Postconditions
  • Safety Invariants: Page table cursor safety invariants are preserved.
  • Correctness: If the target va is within the cursor’s locked range, the result will be Ok and the cursor’s virtual address will be set to va.
  • Correctness: If the target va is outside the locked range, the result is Err.
  • Correctness: If the metadata region was well-formed before the call, it will be well-formed after.
§Safety

This function preserves all memory invariants. Because it throws an error rather than move the cursor to an invalid address, it ensures that the cursor is safe to use after the call. The locking mechanism prevents data races.

Source

pub exec fn virt_addr(&self) -> Vaddr

returns
self.0.va,

Get the virtual address of the current slot.

Auto Trait Implementations§

§

impl<'a, A> !RefUnwindSafe for Cursor<'a, A>

§

impl<'a, A> !UnwindSafe for Cursor<'a, A>

§

impl<'a, A> Freeze for Cursor<'a, A>

§

impl<'a, A> Send for Cursor<'a, A>
where A: Sync,

§

impl<'a, A> Sync for Cursor<'a, A>
where A: Sync,

§

impl<'a, A> Unpin for Cursor<'a, A>

§

impl<'a, A> UnsafeUnpin for Cursor<'a, A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: From<T>,

§

fn obeys_from_spec() -> bool

§

fn from_spec(v: T) -> VERUS_SPEC__A

§

impl<T> FromSpecImpl<T> for T

§

fn obeys_from_spec() -> bool

§

fn from_spec(v: T) -> T

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: Into<T>,

§

fn obeys_into_spec() -> bool

§

fn into_spec(self) -> T

§

impl<T, U> IntoSpecImpl<U> for T
where U: From<T>,

§

fn obeys_into_spec() -> bool

§

fn into_spec(self) -> U

§

impl<T> Pipe for T
where T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
§

impl<A> SpecEq<&A> for A
where A: ?Sized,

§

impl<A> SpecEq<&mut A> for A
where A: ?Sized,

§

impl<A> SpecEq<A> for A
where A: ?Sized,

§

impl<A> SpecEq<Ghost<A>> for A

§

impl<A> SpecEq<Tracked<A>> for A

§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: TryFrom<T>,

§

fn obeys_try_from_spec() -> bool

§

fn try_from_spec( v: T, ) -> Result<VERUS_SPEC__A, <VERUS_SPEC__A as TryFrom<T>>::Error>

Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: TryInto<T>,

§

fn obeys_try_into_spec() -> bool

§

fn try_into_spec(self) -> Result<T, <VERUS_SPEC__A as TryInto<T>>::Error>

§

impl<T, U> TryIntoSpecImpl<U> for T
where U: TryFrom<T>,

§

fn obeys_try_into_spec() -> bool

§

fn try_into_spec(self) -> Result<U, <U as TryFrom<T>>::Error>