use core::sync::atomic::{AtomicU8, Ordering};
struct RpSpinlockCs;
critical_section::set_impl!(RpSpinlockCs);
const LOCK_UNOWNED: u8 = 0;
static LOCK_OWNER: AtomicU8 = AtomicU8::new(LOCK_UNOWNED);
const LOCK_ALREADY_OWNED: u8 = 2;
unsafe impl critical_section::Impl for RpSpinlockCs {
unsafe fn acquire() -> u8 {
RpSpinlockCs::acquire()
}
unsafe fn release(token: u8) {
RpSpinlockCs::release(token);
}
}
impl RpSpinlockCs {
unsafe fn acquire() -> u8 {
let interrupts_active = cortex_m::register::primask::read().is_active();
let core = crate::Sio::core() + 1_u8;
if LOCK_OWNER.load(Ordering::Acquire) == core {
LOCK_ALREADY_OWNED
} else {
loop {
cortex_m::interrupt::disable();
core::sync::atomic::compiler_fence(Ordering::SeqCst);
if let Some(lock) = crate::sio::Spinlock31::try_claim() {
core::mem::forget(lock);
LOCK_OWNER.store(core, Ordering::Relaxed);
break;
}
if interrupts_active {
cortex_m::interrupt::enable();
}
}
interrupts_active as _
}
}
unsafe fn release(token: u8) {
if token != LOCK_ALREADY_OWNED {
LOCK_OWNER.store(LOCK_UNOWNED, Ordering::Relaxed);
core::sync::atomic::compiler_fence(Ordering::SeqCst);
crate::sio::Spinlock31::release();
if token != 0 {
cortex_m::interrupt::enable();
}
}
}
}