implement lock_mut

This commit is contained in:
Jorge Aparicio 2017-04-12 15:27:48 -05:00
parent fb20b51528
commit f62af15cfd
2 changed files with 59 additions and 2 deletions

View file

@ -6,15 +6,16 @@
extern crate cortex_m; extern crate cortex_m;
extern crate typenum; extern crate typenum;
use core::marker::PhantomData;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use core::marker::PhantomData;
use core::ops::Sub;
use cortex_m::interrupt::Nr; use cortex_m::interrupt::Nr;
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
use cortex_m::register::{basepri, basepri_max}; use cortex_m::register::{basepri, basepri_max};
use typenum::{Cmp, Equal, Unsigned}; use typenum::{Cmp, Equal, Unsigned};
#[cfg(not(thumbv6m))] #[cfg(not(thumbv6m))]
use typenum::{Greater, Less}; use typenum::{B1, Greater, Less, Sub1};
pub use cortex_m::ctxt::{Context, Local}; pub use cortex_m::ctxt::{Context, Local};
#[doc(hidden)] #[doc(hidden)]
@ -101,6 +102,10 @@ where
/// For the duration of the critical section, tasks whose priority level is /// For the duration of the critical section, tasks whose priority level is
/// smaller than or equal to the resource `CEILING` will be prevented from /// smaller than or equal to the resource `CEILING` will be prevented from
/// preempting the current task. /// 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))] #[cfg(not(thumbv6m))]
pub fn lock<R, PRIORITY, F>( pub fn lock<R, PRIORITY, F>(
&'static self, &'static self,
@ -130,6 +135,42 @@ where
ret 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> unsafe impl<T, CEILING> Sync for Resource<T, CEILING>

16
tests/cfail/lock_mut.rs Normal file
View file

@ -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
}
);
}