Skip to content

Commit

Permalink
Refactor interrupt masking.
Browse files Browse the repository at this point in the history
  • Loading branch information
zyma98 committed Aug 23, 2024
1 parent 9fa7378 commit 9f9397b
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 73 deletions.
72 changes: 70 additions & 2 deletions src/interrupt/mask.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::config;
use core::sync::atomic::{AtomicUsize, Ordering};
use crate::{config, sync::Holdable};
use core::{
marker::PhantomData,
sync::atomic::{AtomicUsize, Ordering},
};

/// Representing recursively maskable interrupt(s). Recursive means one can
/// `mask_recursive` an already masked interrupt, which will increase the
Expand Down Expand Up @@ -67,6 +70,25 @@ impl RecursivelyMaskable for AllIrqExceptSvc {
pub use core::sync::atomic::{AtomicUsize as __AtomicUsize, Ordering as __Ordering};
pub use paste as __paste;

/// Declare an IRQ to be used with the `IrqSafe` variant of locks, e.g.,
/// [`SpinIrqSafe`](crate::sync::SpinIrqSafe),
/// [`SpinSchedIrqSafe`](crate::sync::SpinSchedIrqSafe),
/// [`MutexIrqSafe`](crate::sync::MutexIrqSafe).
///
/// [`declare_irq`] accepts two arguments as in `declare_irq!($name, $irq)`.
/// The macro expands to produce a type with name `$name` which can be passed
/// to the type construction of `IrqSafe` locks. `$irq` should be an enum
/// variant that implements [`cortex_m::interrupt::InterruptNumber`].
///
/// # Example
/// ```rust
/// /// Produce the type `Tim2Irq`.
/// declare_irq!(Tim2Irq, stm32f4xx_hal::pac::Interrupt::TIM2);
///
/// /// The interrupt `TIM2` will be masked whenever the spin lock is acquired.
/// static TIMER: SpinIrqSafe<stm32f4xx_hal::pac::TIM2>, Tim2Irq>
/// = SpinIrqSafe::new(None);
/// ```
#[macro_export]
macro_rules! declare_irq {
($name:ident, $irq:path) => {
Expand Down Expand Up @@ -97,3 +119,49 @@ macro_rules! declare_irq {
}
};
}

/// Representing interrupt(s) being masked. When the struct is dropped, the
/// masked interrupt(s) will be unmasked if no where else is still masking
/// it. See [`RecursivelyMaskable`] for details.
pub struct HeldInterrupt<I>
where
I: RecursivelyMaskable,
{
_phantom: PhantomData<I>,
}

impl<I> Drop for HeldInterrupt<I>
where
I: RecursivelyMaskable,
{
fn drop(&mut self) {
// Safety: An instance can be created only by calling `hold()` where
// `mask_recursive` would have been called.
unsafe {
I::unmask_recursive();
}
}
}

/// The status of some interrupt being masked should not be sent across
/// different tasks.
impl<I> !Send for HeldInterrupt<I> {}

/// That some interrupts are being masked is a holdable condition.
impl<I> Holdable for I
where
I: RecursivelyMaskable,
{
type GuardType = HeldInterrupt<I>;

fn hold() -> HeldInterrupt<I> {
I::mask_recursive();
HeldInterrupt {
_phantom: PhantomData,
}
}

unsafe fn force_unhold() {
I::unmask_recursive();
}
}
66 changes: 0 additions & 66 deletions src/sync/held_interrupt.rs

This file was deleted.

10 changes: 10 additions & 0 deletions src/sync/lock_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,13 @@ where
H0::force_unhold();
}
}

/// Used when no additional condition needs to be held.
impl Holdable for () {
type GuardType = ();

fn hold() -> () {
()
}
unsafe fn force_unhold() {}
}
2 changes: 0 additions & 2 deletions src/sync/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod channel;
mod condvar;
mod held_interrupt;
mod imported;
mod interruptable;
mod lock_traits;
Expand All @@ -13,7 +12,6 @@ mod wait_queue;

pub use channel::*;
pub use condvar::*;
pub use held_interrupt::*;
pub use imported::*;
pub use interruptable::*;
pub use lock_traits::*;
Expand Down
4 changes: 2 additions & 2 deletions src/sync/mutex.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::{
HeldInterrupt, Holdable, Lockable, SpinGeneric, SpinGenericGuard, SpinSchedSafe,
UnlockableGuard, WaitQueue,
Holdable, Lockable, SpinGeneric, SpinGenericGuard, SpinSchedSafe, UnlockableGuard, WaitQueue,
};
use crate::{
interrupt::mask::HeldInterrupt,
schedule::{
current,
scheduler::{SchedSuspendGuard, Scheduler},
Expand Down
3 changes: 2 additions & 1 deletion src/sync/spin_lock.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{HeldInterrupt, Holdable};
use super::Holdable;
use crate::{
interrupt::mask::HeldInterrupt,
schedule::scheduler::{SchedSuspendGuard, Scheduler},
unrecoverable::Lethal,
};
Expand Down

0 comments on commit 9f9397b

Please sign in to comment.