#[cfg(feature = "smp")]
use core::sync::atomic::AtomicBool;
use core::{cell::UnsafeCell, marker::PhantomData};
use crate::sync::context::{GuardState, PreemptIrqSaveState};
pub struct BaseRawSpinLock<G: GuardState> {
_phantom: PhantomData<G>,
#[cfg(feature = "smp")]
locked: AtomicBool,
state: UnsafeCell<Option<G::State>>,
}
unsafe impl<G: GuardState> Sync for BaseRawSpinLock<G> {}
impl<G: GuardState> BaseRawSpinLock<G> {
pub const fn new() -> Self {
Self {
_phantom: PhantomData,
#[cfg(feature = "smp")]
locked: AtomicBool::new(false),
state: UnsafeCell::new(None),
}
}
#[inline]
fn save_state(&self, state: G::State) {
unsafe {
*self.state.get() = Some(state);
}
}
#[inline]
fn take_state(&self) -> G::State {
unsafe {
(*self.state.get())
.take()
.expect("raw spinlock unlocked without saved guard state")
}
}
}
impl<G: GuardState> Default for BaseRawSpinLock<G> {
fn default() -> Self {
Self::new()
}
}
unsafe impl<G: GuardState + Send + Sync + 'static> lock_api::RawMutex for BaseRawSpinLock<G> {
const INIT: Self = Self::new();
type GuardMarker = lock_api::GuardNoSend;
fn lock(&self) {
let state = G::acquire();
#[cfg(feature = "smp")]
{
super::atomic::spin_acquire(&self.locked, || {
super::atomic::spin_try_acquire_weak(&self.locked)
});
}
self.save_state(state);
}
fn try_lock(&self) -> bool {
let state = G::acquire();
#[cfg(feature = "smp")]
{
if !super::atomic::spin_try_acquire_strong(&self.locked) {
G::release(state);
return false;
}
}
self.save_state(state);
true
}
unsafe fn unlock(&self) {
let state = self.take_state();
#[cfg(feature = "smp")]
super::atomic::spin_release(&self.locked);
G::release(state);
}
}
pub type RawIrqSaveMutex = BaseRawSpinLock<PreemptIrqSaveState>;