Struct rstubs::interrupts::guard::Guard

source ·
pub struct Guard {
    guarded: Ticket<Guarded>,
    active: [AtomicBool; 4],
    epilogues: UnsafeCell<[ArrayDeque<Epilogue, LEN>; 4]>,
}
Expand description

Synchronizes the kernel with interrupts using the Prologue/Epilogue Model

The Guard is used to synchronize between “normal” core activities (currently just the text output, later system calls) and interrupt handling routines. For this purpose, Guard has to contain one or more “queues”, in which Epilogue objects can be added. This is necessary if the critical section is occupied at the time when an interrupt occurs, and the Epilogue::run method cannot be executed immediately. The queued epilogues are processed when leaving the critical section.

The Guard protects and synchronizes various global kernel objects. These objects are only accessible when the guard is locked, by the control flow holding the lock. This prevents concurrent access and race conditions.

§Hints

The epilogue queue is a central data structure, whose consistency must be ensured. The implementation provided by the ArrayDeque is not safe against concurrency, i.e. there must never be accesses by two cores at the same time. You need to disable interrupts during operations on the queue.

For SMP, you need a separate epilogue queue for each core, in which each processor serializes its epilogues. However, epilogues on different cores could then be executed in parallel, since the critical section is managed separately on a per-core basis. This must be prevented by using a global Ticket lock to avoid concurrent execution of epilogues – there must never be more than one epilogue active on the whole system at the same time!

Please note: This giant lock (synchronizing all cores) should not be confused with the (core-specific) flag variable that marks only the entry to the epilogue level on the corresponding core!

Interrupts should be disabled for as short as possible. Due to this reason, the prologue/epilogue model allows epilogues to be interrupted by prologues. This means that interrupts should be enabled again before the epilogue is executed (this includes notifying the APIC about the “End-Of-Interrupt”)

Fields§

§guarded: Ticket<Guarded>§active: [AtomicBool; 4]

Indicates whether the epilogue layer is active on the corresponding core

§epilogues: UnsafeCell<[ArrayDeque<Epilogue, LEN>; 4]>

CPU-local queues for epilogues

Implementations§

source§

impl Guard

source

pub const fn new() -> Self

source

fn epilogues(&self) -> &mut ArrayDeque<Epilogue, LEN>

source

pub unsafe fn read(&self) -> &Guarded

Temporary read-only access.

Safety: beware race conditions!

source

pub fn enter(&self) -> GuardedGuard<'_>

Enter the epilogue layer or wait synchronously if it is already occupied.

A guard object is returned that unlocks the epilogue layer when it falls out of scope.

source

pub fn relay(&self, _epilogue: Epilogue)

Register the given epilogue, which is either executed directly if possible or it is enqueued for later execution.

source

pub fn leave(&self)

Leave the epilogue layer.

source

pub fn active(&self) -> bool

Returns wether the layer 1/2 is active

Trait Implementations§

source§

impl Sync for Guard

Auto Trait Implementations§

§

impl !Freeze for Guard

§

impl !RefUnwindSafe for Guard

§

impl Send for Guard

§

impl Unpin for Guard

§

impl UnwindSafe for Guard

Blanket Implementations§

§

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

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
§

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

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

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

§

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

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

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

§

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> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

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

§

type Error = Infallible

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

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

Performs the conversion.
§

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

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

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.