use core::marker::PhantomData;
use crate::interface::{CONTEXT_IRQSAVE, CONTEXT_PREEMPT, CONTEXT_PREEMPT_IRQSAVE, ContextState};
#[doc(hidden)]
#[inline(always)]
pub fn irq_save_and_disable() -> usize {
crate::interface::context_enter(CONTEXT_IRQSAVE).irq()
}
#[doc(hidden)]
#[inline(always)]
pub unsafe fn irq_restore(state: usize) {
crate::interface::context_exit(CONTEXT_IRQSAVE, ContextState::new(0, 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 = ();
fn acquire() -> Self::State {}
fn release(_state: Self::State) {}
}
impl GuardState for PreemptState {
type State = ContextState;
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 = ContextState;
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 = ContextState;
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: ContextState,
_not_send: PhantomData<*mut ()>,
}
impl PreemptGuard {
pub fn new() -> Self {
Self {
state: PreemptState::acquire(),
_not_send: PhantomData,
}
}
}
impl Default for PreemptGuard {
fn default() -> Self {
Self::new()
}
}
impl Drop for PreemptGuard {
fn drop(&mut self) {
PreemptState::release(self.state);
}
}
pub struct IrqSaveGuard {
state: ContextState,
_not_send: PhantomData<*mut ()>,
}
impl IrqSaveGuard {
pub fn new() -> Self {
Self {
state: IrqSaveState::acquire(),
_not_send: PhantomData,
}
}
pub fn disable_preempt_for_irq_return(&mut self) -> IrqReturnPreemptGuard<'_> {
IrqReturnPreemptGuard {
state: crate::interface::irq_return_preempt_enter(),
_irq_guard: PhantomData,
_not_send: PhantomData,
}
}
}
#[must_use = "dropping the guard completes IRQ-return preemption exit"]
pub struct IrqReturnPreemptGuard<'irq> {
state: usize,
_irq_guard: PhantomData<&'irq mut IrqSaveGuard>,
_not_send: PhantomData<*mut ()>,
}
impl Drop for IrqReturnPreemptGuard<'_> {
fn drop(&mut self) {
crate::interface::irq_return_preempt_exit(self.state);
}
}
pub fn hardirq_enter() {
crate::interface::hardirq_enter();
}
pub fn hardirq_exit() {
crate::interface::hardirq_exit();
}
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: ContextState,
_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);
}
}