From e1567ad70724937865bda642dd3a7d5422451684 Mon Sep 17 00:00:00 2001 From: Allen Welkie Date: Sat, 19 Nov 2016 13:20:22 -0500 Subject: [PATCH] Add CritToken struct --- CHANGELOG.md | 8 ++++++++ src/interrupt.rs | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e7ac7b7..a2122613 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- `interrupt::CritToken`, a struct that only exists in a critical section. + +### Changed + +- The closure that `interrupt::free` takes now takes a reference to an `interrupt::CritToken`. + ## [v0.1.5] ### Added diff --git a/src/interrupt.rs b/src/interrupt.rs index 43050717..34f3049c 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -22,13 +22,22 @@ impl Mutex { pub fn lock(&self, f: F) -> R where F: FnOnce(&mut T) -> R { - unsafe { ::interrupt::free(|| f(&mut *self.inner.get())) } + unsafe { ::interrupt::free(|_| f(&mut *self.inner.get())) } } } // FIXME `T` should have some bound: `Send` or `Sync`? unsafe impl Sync for Mutex {} +/// A struct whos existence guarantees that interrupts are disabled +/// +/// This struct is zero-sized and cannot be initialized by user code. An +/// instance is only ever created in the `free` function, which passes the +/// instance to the closure. This allows a user to force a function to only +/// ever be called in a critical section by taking a reference to a `CritToken` +/// as a parameter. +pub struct CritToken(()); + /// Disable interrupts, globally #[inline(always)] pub unsafe fn disable() { @@ -58,13 +67,13 @@ 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) -> R - where F: FnOnce() -> R + where F: FnOnce(&CritToken) -> R { let primask = ::register::primask::read(); disable(); - let r = f(); + let r = f(&CritToken(())); // If the interrupts were enabled before our `disable` call, then re-enable // them. Otherwise, keep them disabled