feat: replace NullLock with SpinLock

This commit is contained in:
2021-10-21 19:10:41 +03:00
parent 67d49f8f0e
commit 24acc37cc1
15 changed files with 83 additions and 67 deletions
+37 -16
View File
@@ -1,63 +1,84 @@
//! Synchronization facilities module
use crate::arch::platform::{irq_mask_save, irq_restore};
use core::sync::atomic::{AtomicBool, Ordering};
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
/// Lock structure ensuring IRQs are disabled when inner value is accessed
pub struct IrqSafeNullLock<T: ?Sized> {
pub struct IrqSafeSpinLock<T> {
value: UnsafeCell<T>,
state: AtomicBool
}
/// Guard-structure wrapping a reference to value owned by [IrqSafeNullLock].
/// Guard-structure wrapping a reference to value owned by [IrqSafeSpinLock].
/// Restores saved IRQ state when dropped.
pub struct IrqSafeNullLockGuard<'a, T: ?Sized> {
value: &'a mut T,
pub struct IrqSafeSpinLockGuard<'a, T> {
lock: &'a IrqSafeSpinLock<T>,
irq_state: u64,
}
impl<T> IrqSafeNullLock<T> {
impl<T> IrqSafeSpinLock<T> {
/// Constructs a new instance of the lock, wrapping `value`
#[inline(always)]
pub const fn new(value: T) -> Self {
Self {
value: UnsafeCell::new(value),
state: AtomicBool::new(false)
}
}
/// Returns [IrqSafeNullLockGuard] for this lock
#[inline(always)]
fn try_lock(&self) -> Result<bool, bool> {
self.state.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
}
#[inline(always)]
unsafe fn force_release(&self) {
self.state.store(false, Ordering::Release);
cortex_a::asm::sev();
}
/// Returns [IrqSafeSpinLockGuard] for this lock
#[inline]
pub fn lock(&self) -> IrqSafeNullLockGuard<T> {
pub fn lock(&self) -> IrqSafeSpinLockGuard<T> {
let irq_state = unsafe { irq_mask_save() };
while self.try_lock().is_err() {
cortex_a::asm::wfe();
}
unsafe {
IrqSafeNullLockGuard {
value: &mut *self.value.get(),
irq_state: irq_mask_save(),
IrqSafeSpinLockGuard {
lock: self,
irq_state
}
}
}
}
impl<T: ?Sized> Deref for IrqSafeNullLockGuard<'_, T> {
impl<T> Deref for IrqSafeSpinLockGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.value
unsafe { &*self.lock.value.get() }
}
}
impl<T: ?Sized> DerefMut for IrqSafeNullLockGuard<'_, T> {
impl<T> DerefMut for IrqSafeSpinLockGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.value
unsafe { &mut *self.lock.value.get() }
}
}
impl<T: ?Sized> Drop for IrqSafeNullLockGuard<'_, T> {
impl<T> Drop for IrqSafeSpinLockGuard<'_, T> {
#[inline(always)]
fn drop(&mut self) {
unsafe {
self.lock.force_release();
irq_restore(self.irq_state);
}
}
}
unsafe impl<T: ?Sized> Sync for IrqSafeNullLock<T> {}
unsafe impl<T> Sync for IrqSafeSpinLock<T> {}