aboutsummaryrefslogtreecommitdiff
path: root/src/interrupt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/interrupt.rs')
-rw-r--r--src/interrupt.rs76
1 files changed, 50 insertions, 26 deletions
diff --git a/src/interrupt.rs b/src/interrupt.rs
index 4305071..e11fdc3 100644
--- a/src/interrupt.rs
+++ b/src/interrupt.rs
@@ -15,62 +15,86 @@ impl<T> Mutex<T> {
}
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())) }
+ /// Borrows the data for the duration of the critical section
+ pub fn borrow<'cs>(&self, _ctxt: &'cs CriticalSection) -> &'cs T {
+ unsafe { &*self.inner.get() }
}
+
+ /// Mutably borrows the data for the duration of the critical section
+ pub fn borrow_mut<'cs>(
+ &self,
+ _ctxt: &'cs mut CriticalSection,
+ ) -> &'cs mut T {
+ unsafe { &mut *self.inner.get() }
+ }
+}
+
+/// Interrupt number
+pub unsafe trait Nr {
+ /// Returns the number associated with this interrupt
+ fn nr(&self) -> u8;
}
-// FIXME `T` should have some bound: `Send` or `Sync`?
unsafe impl<T> Sync for Mutex<T> {}
-/// Disable interrupts, globally
+/// Disables all interrupts
#[inline(always)]
-pub unsafe fn disable() {
+pub fn disable() {
match () {
#[cfg(target_arch = "arm")]
- () => {
- asm!("cpsid i" :::: "volatile");
- }
+ () => unsafe {
+ asm!("cpsid i"
+ :
+ :
+ :
+ : "volatile");
+ },
#[cfg(not(target_arch = "arm"))]
() => {}
}
}
-/// Enable interrupts, globally
+/// Enables all the interrupts
#[inline(always)]
-pub unsafe fn enable() {
+pub fn enable() {
match () {
#[cfg(target_arch = "arm")]
- () => {
- asm!("cpsie i" :::: "volatile");
- }
+ () => unsafe {
+ asm!("cpsie i"
+ :
+ :
+ :
+ : "volatile");
+ },
#[cfg(not(target_arch = "arm"))]
() => {}
}
}
+/// Critical section context
+///
+/// Indicates that you are executing code within a critical section
+pub struct CriticalSection {
+ _0: (),
+}
+
/// Execute closure `f` in an interrupt-free context.
+///
/// This as also known as a "critical section".
-pub unsafe fn free<F, R>(f: F) -> R
- where F: FnOnce() -> R
+pub fn free<F, R>(f: F) -> R
+where
+ F: FnOnce(CriticalSection) -> R,
{
let primask = ::register::primask::read();
+ // disable interrupts
disable();
- let r = f();
+ let r = f(CriticalSection { _0: () });
- // If the interrupts were enabled before our `disable` call, then re-enable
+ // If the interrupts were active 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 {
+ if primask.is_active() {
enable();
}