use core::marker::PhantomData;
use crate::interface::{CONTEXT_IRQSAVE, CONTEXT_PREEMPT, CONTEXT_PREEMPT_IRQSAVE, CONTEXT_RAW};
#[doc(hidden)]
#[inline(always)]
pub fn irq_save_and_disable() -> usize {
crate::interface::context_enter(CONTEXT_IRQSAVE)
}
#[doc(hidden)]
#[inline(always)]
pub unsafe fn irq_restore(state: usize) {
crate::interface::context_exit(CONTEXT_IRQSAVE, state);
}
#[doc(hidden)]
pub trait GuardState {
type State: Clone + Copy;
fn acquire() -> Self::State;
fn release(state: Self::State);
}
#[doc(hidden)]
pub struct RawState;
#[doc(hidden)]
pub struct PreemptState;
#[doc(hidden)]
pub struct IrqSaveState;
#[doc(hidden)]
pub struct PreemptIrqSaveState;
impl GuardState for RawState {
type State = usize;
fn acquire() -> Self::State {
crate::interface::context_enter(CONTEXT_RAW)
}
fn release(state: Self::State) {
crate::interface::context_exit(CONTEXT_RAW, state);
}
}
impl GuardState for PreemptState {
type State = usize;
fn acquire() -> Self::State {
crate::interface::context_enter(CONTEXT_PREEMPT)
}
fn release(state: Self::State) {
crate::interface::context_exit(CONTEXT_PREEMPT, state);
}
}
impl GuardState for IrqSaveState {
type State = usize;
fn acquire() -> Self::State {
crate::interface::context_enter(CONTEXT_IRQSAVE)
}
fn release(state: Self::State) {
crate::interface::context_exit(CONTEXT_IRQSAVE, state);
}
}
impl GuardState for PreemptIrqSaveState {
type State = usize;
fn acquire() -> Self::State {
crate::interface::context_enter(CONTEXT_PREEMPT_IRQSAVE)
}
fn release(state: Self::State) {
crate::interface::context_exit(CONTEXT_PREEMPT_IRQSAVE, state);
}
}
pub struct PreemptGuard {
state: Option<usize>,
_not_send: PhantomData<*mut ()>,
}
impl PreemptGuard {
pub fn new() -> Self {
Self {
state: Some(PreemptState::acquire()),
_not_send: PhantomData,
}
}
#[doc(hidden)]
pub fn finish_irq_return(mut self) {
let state = self
.state
.take()
.expect("IRQ-return preemption state must be present");
crate::interface::preempt_exit_from_irq_return(state);
}
}
impl Default for PreemptGuard {
fn default() -> Self {
Self::new()
}
}
impl Drop for PreemptGuard {
fn drop(&mut self) {
if let Some(state) = self.state.take() {
PreemptState::release(state);
}
}
}
pub struct IrqSaveGuard {
state: usize,
_not_send: PhantomData<*mut ()>,
}
impl IrqSaveGuard {
pub fn new() -> Self {
Self {
state: IrqSaveState::acquire(),
_not_send: PhantomData,
}
}
}
impl Default for IrqSaveGuard {
fn default() -> Self {
Self::new()
}
}
impl Drop for IrqSaveGuard {
fn drop(&mut self) {
IrqSaveState::release(self.state);
}
}
pub struct PreemptIrqSaveGuard {
state: usize,
_not_send: PhantomData<*mut ()>,
}
impl PreemptIrqSaveGuard {
pub fn new() -> Self {
Self {
state: PreemptIrqSaveState::acquire(),
_not_send: PhantomData,
}
}
}
impl Default for PreemptIrqSaveGuard {
fn default() -> Self {
Self::new()
}
}
impl Drop for PreemptIrqSaveGuard {
fn drop(&mut self) {
PreemptIrqSaveState::release(self.state);
}
}