summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mutex.rs61
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}
+ }
+}