From e0034b6e9d7d15bcd5a5b9990e31d26c887846d5 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Tue, 21 Apr 2020 21:14:43 +0200 Subject: [PATCH 1/4] Added arch specific mutex implementation --- Cargo.toml | 1 + src/lib.rs | 1 + src/mutex.rs | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 src/mutex.rs diff --git a/Cargo.toml b/Cargo.toml index 5137dce5..b1c61141 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ links = "cortex-m" # prevent multiple versions of this crate to be linked toget [dependencies] bare-metal = { version = "0.2.0", features = ["const-fn"] } volatile-register = "0.2.0" +mutex-trait = "0.2.0" [features] cm7-r0p1 = [] diff --git a/src/lib.rs b/src/lib.rs index f8b56060..52870413 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,5 +62,6 @@ pub mod interrupt; pub mod itm; pub mod peripheral; pub mod register; +pub mod mutex; pub use crate::peripheral::Peripherals; diff --git a/src/mutex.rs b/src/mutex.rs new file mode 100644 index 00000000..7346e354 --- /dev/null +++ b/src/mutex.rs @@ -0,0 +1,25 @@ +//! Implementation of a critical section based mutex that also implements the `mutex-trait`. + +use core::cell::RefCell; + +/// A critical section based mutex +pub struct CriticalSectionMutex { + data: RefCell, +} + +impl CriticalSectionMutex { + /// Create a new mutex + pub const fn new(data: T) -> Self { + CriticalSectionMutex { + data: RefCell::new(data), + } + } +} + +impl mutex_trait::Mutex for &'_ CriticalSectionMutex { + type Data = T; + + fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { + crate::interrupt::free(|_| f(&mut *self.data.borrow_mut())) + } +} From 64ff1e185001fdb3d56b7fc166db08713e0d97d2 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Tue, 21 Apr 2020 21:56:47 +0200 Subject: [PATCH 2/4] UnsafeCell test --- src/mutex.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mutex.rs b/src/mutex.rs index 7346e354..69485120 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -1,17 +1,17 @@ //! Implementation of a critical section based mutex that also implements the `mutex-trait`. -use core::cell::RefCell; +use core::cell::UnsafeCell; /// A critical section based mutex pub struct CriticalSectionMutex { - data: RefCell, + data: UnsafeCell, } impl CriticalSectionMutex { /// Create a new mutex pub const fn new(data: T) -> Self { CriticalSectionMutex { - data: RefCell::new(data), + data: UnsafeCell::new(data), } } } @@ -20,6 +20,11 @@ impl mutex_trait::Mutex for &'_ CriticalSectionMutex { type Data = T; fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { - crate::interrupt::free(|_| f(&mut *self.data.borrow_mut())) + crate::interrupt::free(|_| f(unsafe { &mut *self.data.get() })) } } + +// NOTE A `Mutex` can be used as a channel so the protected data must be `Send` +// to prevent sending non-Sendable stuff (e.g. access tokens) across different +// execution contexts (e.g. interrupts) +unsafe impl Sync for CriticalSectionMutex where T: Send {} From b4635839218108d4c68158ad38ca26e063137f79 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Tue, 21 Apr 2020 21:57:13 +0200 Subject: [PATCH 3/4] Update src/mutex.rs Co-Authored-By: Jonas Schievink --- src/mutex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mutex.rs b/src/mutex.rs index 69485120..86bd5d55 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -2,7 +2,7 @@ use core::cell::UnsafeCell; -/// A critical section based mutex +/// A critical section based mutex. pub struct CriticalSectionMutex { data: UnsafeCell, } From 2dca8c948f47a1c23e9f33bff26721f5a33f2fd8 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Tue, 21 Apr 2020 22:03:48 +0200 Subject: [PATCH 4/4] More docs --- src/mutex.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mutex.rs b/src/mutex.rs index 86bd5d55..0975b83c 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -1,4 +1,8 @@ //! Implementation of a critical section based mutex that also implements the `mutex-trait`. +//! +//! ## Safety +//! +//! Note that this is only safe in single core applications. use core::cell::UnsafeCell;