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.unwrap()) == Some(range)

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

    }
}
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<'rcu, UserPtConfig>>,
requires
old(self).0.invariants(*old(owner), *old(regions), *old(guards)),
old(owner).in_locked_range(),
ensures
self.0.invariants(*owner, *regions, *guards),
self.0.query_some_condition(*owner)
    ==> {
        &&& r is Ok
        &&& self.0.query_some_ensures(*owner, r.unwrap())

    },
!self.0.query_some_condition(*owner)
    ==> {
        &&& r is Ok
        &&& self.0.query_none_ensures(*owner, r.unwrap())

    },

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<'rcu, UserPtConfig>>,
requires
old(self).0.invariants(*old(owner), *old(regions), *old(guards)),
old(self).0.level < old(self).0.guard_level,
old(owner).in_locked_range(),
len % PAGE_SIZE == 0,
old(self).0.va + len <= old(self).0.barrier_va.end,
ensures
self.0.invariants(*owner, *regions, *guards),
res is Some
    ==> {
        &&& res.unwrap() == self.0.va
        &&& owner.level < owner.guard_level
        &&& 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
  • Liveness: The cursor must be within the locked range and below the guard level.
  • Liveness: The length must be page-aligned and less than or equal to the remaining range of the cursor.
§Postconditions
  • 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.
  • If not, it will return None. The cursor may stop at any address after len bytes, but it will not move past the barrier address.
§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. The locking mechanism prevents data races.

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<'rcu, UserPtConfig>>,
requires
old(self).0.invariants(*old(owner), *old(regions), *old(guards)),
old(self).0.level < old(self).0.guard_level,
old(owner).in_locked_range(),
old(self).0.jump_panic_condition(va),
ensures
self.0.invariants(*owner, *regions, *guards),
self.0.barrier_va.start <= va < self.0.barrier_va.end
    ==> {
        &&& res is Ok
        &&& self.0.va == va

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

Jump to the virtual address.

This function will move the cursor to the given virtual address. If the target address is not in the locked range, it will return an error.

§Verified Properties
§Preconditions

The cursor must be within the locked range and below the guard level.

§Postconditions
  • If the target address is in the locked range, it will move the cursor to the given address.
  • If the target address is not in the locked range, it will return an error.
§Panics

This method panics if the target address is not aligned to the page size.

§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

Get the virtual address of the current slot.

Auto Trait Implementations§

§

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

§

impl<'a, A> !RefUnwindSafe 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> !UnwindSafe 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
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

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

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>