add cortex_a9::mutex

master
Astro 2019-11-18 02:13:54 +01:00
parent 85f29ace6b
commit 4e4ff512d9
2 changed files with 74 additions and 0 deletions

View File

@ -2,5 +2,6 @@ pub mod asm;
pub mod regs;
pub mod cache;
pub mod mmu;
pub mod mutex;
global_asm!(include_str!("exceptions.s"));

73
src/cortex_a9/mutex.rs Normal file
View File

@ -0,0 +1,73 @@
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicBool, Ordering};
use core::cell::UnsafeCell;
use super::asm::*;
#[inline]
fn wait_for_update() {
wfe();
}
#[inline]
fn signal_update() {
dsb();
sev();
}
pub struct Mutex<T> {
locked: AtomicBool,
inner: UnsafeCell<T>,
}
unsafe impl<T: Send> Sync for Mutex<T> {}
unsafe impl<T: Send> Send for Mutex<T> {}
impl<T> Mutex<T> {
pub const fn new(inner: T) -> Self {
Mutex{
locked: AtomicBool::new(false),
inner: UnsafeCell::new(inner),
}
}
pub fn lock(&self) -> MutexGuard<T> {
while self.locked.compare_and_swap(false, true, Ordering::Acquire) {
while self.locked.load(Ordering::Relaxed) {
wait_for_update();
}
}
dmb();
MutexGuard { mutex: self }
}
fn unlock(&self) {
dmb();
self.locked.store(false, Ordering::Release);
signal_update();
}
}
pub struct MutexGuard<'a, T> {
mutex: &'a Mutex<T>,
}
impl<'a, T> Deref for MutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.mutex.inner.get() }
}
}
impl<'a, T> DerefMut for MutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.mutex.inner.get() }
}
}
impl<'a, T> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
self.mutex.unlock();
}
}