diff options
| author | Jorge Aparicio <japaricious@gmail.com> | 2017-04-12 15:27:48 -0500 |
|---|---|---|
| committer | Jorge Aparicio <japaricious@gmail.com> | 2017-04-12 15:27:48 -0500 |
| commit | f62af15cfd1491219fab4345abd7f21a6418e45f (patch) | |
| tree | 4bd837200ede15c914460f70d90015339299a920 | |
| parent | fb20b5152822462de2b5482f590c8f18078ec70b (diff) | |
implement lock_mut
| -rw-r--r-- | src/lib.rs | 45 | ||||
| -rw-r--r-- | tests/cfail/lock_mut.rs | 16 |
2 files changed, 59 insertions, 2 deletions
@@ -6,15 +6,16 @@ extern crate cortex_m; extern crate typenum; -use core::marker::PhantomData; use core::cell::UnsafeCell; +use core::marker::PhantomData; +use core::ops::Sub; use cortex_m::interrupt::Nr; #[cfg(not(thumbv6m))] use cortex_m::register::{basepri, basepri_max}; use typenum::{Cmp, Equal, Unsigned}; #[cfg(not(thumbv6m))] -use typenum::{Greater, Less}; +use typenum::{B1, Greater, Less, Sub1}; pub use cortex_m::ctxt::{Context, Local}; #[doc(hidden)] @@ -101,6 +102,10 @@ where /// For the duration of the critical section, tasks whose priority level is /// smaller than or equal to the resource `CEILING` will be prevented from /// preempting the current task. + /// + /// Within this critical section, resources with ceiling equal to or smaller + /// than `CEILING` can be borrowed at zero cost. See + /// [Resource.borrow](struct.Resource.html#method.borrow). #[cfg(not(thumbv6m))] pub fn lock<R, PRIORITY, F>( &'static self, @@ -130,6 +135,42 @@ where ret } } + + /// Like [Resource.lock](struct.Resource.html#method.lock) but returns a + /// `&mut-` reference + /// + /// This method has additional an additional constraint: you can't borrow a + /// resource that has ceiling equal `CEILING`. This constraint is required + /// to preserve Rust aliasing rules. + pub fn lock_mut<R, PRIORITY, F>( + &'static self, + _priority: &mut P<PRIORITY>, + f: F, + ) -> R + where + F: FnOnce(&mut T, C<Sub1<CEILING>>) -> R, + C<CEILING>: Ceiling, + CEILING: Sub<B1>, + CEILING: Cmp<PRIORITY, Output = Greater> + Cmp<UMAX, Output = Less> + + Level, + P<PRIORITY>: Priority, + { + unsafe { + let old_basepri = basepri::read(); + basepri_max::write(<CEILING>::hw()); + barrier!(); + let ret = f( + &mut *self.data.get(), + C { + _0: (), + _marker: PhantomData, + }, + ); + barrier!(); + basepri::write(old_basepri); + ret + } + } } unsafe impl<T, CEILING> Sync for Resource<T, CEILING> diff --git a/tests/cfail/lock_mut.rs b/tests/cfail/lock_mut.rs new file mode 100644 index 0000000..b5e1ae9 --- /dev/null +++ b/tests/cfail/lock_mut.rs @@ -0,0 +1,16 @@ +extern crate cortex_m_srp; + +use cortex_m_srp::{C3, C4, P2, Resource}; + +static R1: Resource<i32, C4> = Resource::new(0); +static R2: Resource<i32, C3> = Resource::new(0); + +fn j1(mut prio: P2) { + R1.lock_mut( + &mut prio, |r1: &mut i32, c3| { + let r2 = R2.borrow(&c3); + let another_r1: &i32 = R1.borrow(&c3); + //~^ error + } + ); +} |
