From bad8851fee64d82a24c6ec8406358098c85cf3e3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 20 May 2017 12:23:52 -0500 Subject: [PATCH] add `Resource.read` method for atomic reads of a resource's value this method lets you directly read the value of a resource without paying for synchronization overhead (no need for `Threshold.raise`). The catch is that resource value must have a size of 4-bytes or smaller to guarantee that the read operation is atomic -- atomic as in it can't be interrupted. --- src/lib.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index de7fd1949e..9666f1fe2b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -426,9 +426,9 @@ extern crate cortex_m; extern crate static_ref; extern crate typenum; -use core::cell::UnsafeCell; +use core::cell::{Cell, UnsafeCell}; use core::marker::PhantomData; -use core::ptr; +use core::{mem, ptr}; use cortex_m::ctxt::Context; use cortex_m::interrupt::Nr; @@ -536,6 +536,29 @@ impl Resource { } } +impl Resource, RC> { + /// Performs an atomic read of the resource value + /// + /// This method has no synchronization overhead, and doesn't impose + /// additional task blocking + /// + /// # Panics + /// + /// - This method will panic if the size of `T` is greater than the size + /// of a word (4 bytes) + pub fn read(&self) -> T { + assert!(mem::size_of::() <= mem::size_of::()); + + // NOTE(volatile) this has to be volatile because unlike a read through + // `access` there's no guarantee that the resource value will *not* + // change between two consecutive reads (e.g. an interrupt may occur + // in between) + unsafe { + ptr::read_volatile(self.data.get() as *const _) + } + } +} + unsafe impl Sync for Resource where T: Send,