diff options
-rw-r--r-- | src/mutex.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/mutex.rs b/src/mutex.rs new file mode 100644 index 0000000..1da3890 --- /dev/null +++ b/src/mutex.rs @@ -0,0 +1,61 @@ +use core::ops::{Deref, DerefMut}; +use core::cell::UnsafeCell; + +pub struct Mutex<T> { + res: UnsafeCell<T>, + locked: u8 +} + +pub struct MutexGuard<'a, T: 'a> { + lock: &'a Mutex<T> +} + +impl<'a, T> Drop for MutexGuard<'a, T> { + fn drop(&mut self) { + unsafe { + asm!("ldr r2, $0 + mov r1, $1 + dmb + str r1, [r2]" + : + : "m"(&self.lock.locked), "i"(0)); + } + } +} + +impl<'a, T> Deref for MutexGuard<'a, T> { + type Target = T; + fn deref(&self) -> &Self::Target { + unsafe { &*self.lock.res.get() } + } +} + +impl<'a, T> DerefMut for MutexGuard<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.lock.res.get() } + } +} + +impl<T> Mutex<T> { + pub fn new(t: T) -> Mutex<T> { + Mutex{res: UnsafeCell::new(t), locked: 0} + } + pub fn lock(&self) -> MutexGuard<T> { + unsafe { + asm!("ldr r2, $0 + mov r1, $1 + spin_lock: + ldrex r0, [r2] + cmp r0, $1 + itt ne + strexbne r0, r1, [r2] + cmpne r0, #1 + beq spin_lock + dmb" + : + : "m"(&self.locked), "i"(1) + : "r2", "r1", "r0"); + } + MutexGuard{lock: self} + } +} |