diff options
author | 2016-10-30 10:27:06 -0500 | |
---|---|---|
committer | 2016-11-19 09:59:00 -0500 | |
commit | 0b774e9e9850ca483afaf89c09ee2e5841050fa7 (patch) | |
tree | 912b250835e40553280d37203b9b214fbec0a138 | |
parent | 9d97ed3e739dba4c9bff0a4733035a355a91b896 (diff) | |
download | cortex-m-0b774e9e9850ca483afaf89c09ee2e5841050fa7.tar.gz cortex-m-0b774e9e9850ca483afaf89c09ee2e5841050fa7.tar.zst cortex-m-0b774e9e9850ca483afaf89c09ee2e5841050fa7.zip |
add a mutex based on critical sections
-rw-r--r-- | src/interrupt.rs | 41 | ||||
-rw-r--r-- | src/lib.rs | 1 |
2 files changed, 37 insertions, 5 deletions
diff --git a/src/interrupt.rs b/src/interrupt.rs index 6fb8aeb..4305071 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -1,5 +1,34 @@ //! Interrupts +use core::cell::UnsafeCell; + +/// A "mutex" based on critical sections +pub struct Mutex<T> { + inner: UnsafeCell<T>, +} + +impl<T> Mutex<T> { + /// Creates a new mutex + pub const fn new(value: T) -> Self { + Mutex { inner: UnsafeCell::new(value) } + } +} + +impl<T> Mutex<T> { + /// Gets access to the inner data + /// + /// NOTE this prevents interrupts handlers from running thus gaining + /// exclusive access to the processor + pub fn lock<F, R>(&self, f: F) -> R + where F: FnOnce(&mut T) -> R + { + unsafe { ::interrupt::free(|| f(&mut *self.inner.get())) } + } +} + +// FIXME `T` should have some bound: `Send` or `Sync`? +unsafe impl<T> Sync for Mutex<T> {} + /// Disable interrupts, globally #[inline(always)] pub unsafe fn disable() { @@ -28,20 +57,22 @@ pub unsafe fn enable() { /// Execute closure `f` in an interrupt-free context. /// This as also known as a "critical section". -pub unsafe fn free<F>(f: F) - where F: FnOnce() +pub unsafe fn free<F, R>(f: F) -> R + where F: FnOnce() -> R { let primask = ::register::primask::read(); disable(); - f(); + let r = f(); - // If the interrupts were enabled before our `disable` call, then re-enable them - // Otherwise, keep them disabled + // If the interrupts were enabled before our `disable` call, then re-enable + // them. Otherwise, keep them disabled // PRIMASK & 1 = 1 indicates that the interrupts were disabled // PRIMASK & 1 = 0 indicates that they were enabled if primask & 1 == 0 { enable(); } + + r } @@ -12,6 +12,7 @@ #![deny(missing_docs)] #![deny(warnings)] #![feature(asm)] +#![feature(const_fn)] #![no_std] extern crate volatile_register; |