Struct kernel::grant::ProcessGrant

source ·
pub struct ProcessGrant<'a, T: 'a, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: AllowRwSize> { /* private fields */ }
Expand description

An instance of a grant allocated for a particular process.

ProcessGrant is a handle to an instance of a grant that has been allocated in a specific process’s grant region. A ProcessGrant guarantees that the memory for the grant has been allocated in the process’s memory.

This is created from a Grant when that grant is entered for a specific process.

Implementations§

source§

impl<'a, T: Default, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: AllowRwSize> ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>

source

pub fn processid(&self) -> ProcessId

Return the ProcessId of the process this ProcessGrant is associated with.

source

pub fn enter<F, R>(self, fun: F) -> R
where F: FnOnce(&mut GrantData<'_, T>, &GrantKernelData<'_>) -> R,

Run a function with access to the memory in the related process for the related Grant. This also provides access to any associated Upcalls and allowed buffers stored with the grant.

This is “entering” the grant region, and the only time when the contents of a grant region can be accessed.

Note, a grant can only be entered once at a time. Attempting to call .enter() on a grant while it is already entered will result in a panic!(). See the comment in access_grant()` for more information.

source

pub fn try_enter<F, R>(self, fun: F) -> Option<R>
where F: FnOnce(&mut GrantData<'_, T>, &GrantKernelData<'_>) -> R,

Run a function with access to the data in the related process for the related Grant only if that grant region is not already entered. If the grant is already entered silently skip it. Also provide access to associated Upcalls.

You almost certainly should use .enter() rather than .try_enter().

While the .enter() version can panic, that panic likely indicates a bug in the code and not a condition that should be handled. For example, this benign looking code is wrong:

self.apps.enter(thisapp, |app_grant, _| {
    // Update state in the grant region of `thisapp`. Also, mark that
    // `thisapp` needs to run again.
    app_grant.runnable = true;

    // Now, check all apps to see if any are ready to run.
    let mut work_left_to_do = false;
    self.apps.iter().each(|other_app| {
        other_app.enter(|other_app_grant, _| { // ERROR! This leads to a
            if other_app_grant.runnable {      // grant being entered
                work_left_to_do = true;        // twice!
            }
        })
    })
})

The example is wrong because it tries to iterate across all grant regions while one of them is already entered. This will lead to a grant region being entered twice which violates Rust’s memory restrictions and is undefined behavior.

However, since the example uses .enter() on the iteration, Tock will panic when the grant is entered for the second time, notifying the developer that something is wrong. The fix is to exit out of the first .enter() before attempting to iterate over the grant for all processes.

However, if the example used .try_enter() in the iter loop, there would be no panic, but the already entered grant would be silently skipped. This can hide subtle bugs if the skipped grant is only relevant in certain cases.

Therefore, only use try_enter() if you are sure you want to skip the already entered grant. Cases for this are rare.

§Return

Returns None if the grant is already entered. Otherwise returns Some(fun()).

source

pub fn enter_with_allocator<F, R>(self, fun: F) -> R
where F: FnOnce(&mut GrantData<'_, T>, &GrantKernelData<'_>, &mut GrantRegionAllocator) -> R,

Run a function with access to the memory in the related process for the related Grant. Also provide this function with access to any associated Upcalls and an allocator for allocating additional memory in the process’s grant region.

This is “entering” the grant region, and the only time when the contents of a grant region can be accessed.

Note, a grant can only be entered once at a time. Attempting to call .enter() on a grant while it is already entered will result in a panic!(). See the comment in access_grant()` for more information.

Auto Trait Implementations§

§

impl<'a, T, Upcalls, AllowROs, AllowRWs> Freeze for ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>

§

impl<'a, T, Upcalls, AllowROs, AllowRWs> !RefUnwindSafe for ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>

§

impl<'a, T, Upcalls, AllowROs, AllowRWs> !Send for ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>

§

impl<'a, T, Upcalls, AllowROs, AllowRWs> !Sync for ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>

§

impl<'a, T, Upcalls, AllowROs, AllowRWs> Unpin for ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>
where T: Unpin, Upcalls: Unpin, AllowROs: Unpin, AllowRWs: Unpin,

§

impl<'a, T, Upcalls, AllowROs, AllowRWs> !UnwindSafe for ProcessGrant<'a, T, Upcalls, AllowROs, AllowRWs>

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.

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.

source§

impl<T> SizedTypeProperties for T

source§

#[doc(hidden)] const IS_ZST: bool = _

🔬This is a nightly-only experimental API. (sized_type_properties)
true if this type requires no storage. false if its size is greater than zero. Read more
source§

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

§

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.
source§

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

§

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.