mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
require Resource protected data to be Send, make tokens !Send
This commit is contained in:
parent
fc4cb7d472
commit
c1a0f8173a
2 changed files with 171 additions and 1 deletions
13
src/lib.rs
13
src/lib.rs
|
@ -419,6 +419,7 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate cortex_m;
|
extern crate cortex_m;
|
||||||
|
@ -533,7 +534,11 @@ impl<T, RC> Resource<T, Ceiling<RC>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T, C> Sync for Resource<T, C> {}
|
unsafe impl<T, C> Sync for Resource<T, C>
|
||||||
|
where
|
||||||
|
T: Send,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// A hardware peripheral as a resource
|
/// A hardware peripheral as a resource
|
||||||
///
|
///
|
||||||
|
@ -684,6 +689,8 @@ pub struct Ceiling<N> {
|
||||||
_marker: PhantomData<N>,
|
_marker: PhantomData<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N> !Send for Ceiling<N> {}
|
||||||
|
|
||||||
/// Preemption threshold
|
/// Preemption threshold
|
||||||
pub struct Threshold<T> {
|
pub struct Threshold<T> {
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
|
@ -710,6 +717,8 @@ impl<PT> Threshold<PT> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N> !Send for Threshold<N> {}
|
||||||
|
|
||||||
/// Priority
|
/// Priority
|
||||||
pub struct Priority<N> {
|
pub struct Priority<N> {
|
||||||
_marker: PhantomData<N>,
|
_marker: PhantomData<N>,
|
||||||
|
@ -725,6 +734,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N> !Send for Priority<N> {}
|
||||||
|
|
||||||
/// Maps a `Resource` / `Peripheral` to its ceiling
|
/// Maps a `Resource` / `Peripheral` to its ceiling
|
||||||
///
|
///
|
||||||
/// Do not implement this trait yourself. This is an implementation detail.
|
/// Do not implement this trait yourself. This is an implementation detail.
|
||||||
|
|
159
tests/cfail/token-transfer.rs
Normal file
159
tests/cfail/token-transfer.rs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
#![feature(const_fn)]
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
#![feature(used)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate cortex_m_rtfm as rtfm;
|
||||||
|
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
|
use rtfm::{C2, Local, P0, P1, P2, Resource, T0, T1, T2, TMax};
|
||||||
|
use device::interrupt::{Exti0, Exti1};
|
||||||
|
|
||||||
|
tasks!(device, {
|
||||||
|
t1: Task {
|
||||||
|
interrupt: Exti0,
|
||||||
|
priority: P1,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
t2: Task {
|
||||||
|
interrupt: Exti1,
|
||||||
|
priority: P2,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fn init(_: P0, _: &TMax) {}
|
||||||
|
|
||||||
|
fn idle(_: P0, _: T0) -> ! {
|
||||||
|
rtfm::request(t1);
|
||||||
|
rtfm::request(t1);
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CHANNEL: Resource<RefCell<Option<Exti0>>, C2> = {
|
||||||
|
//~^ error: Send
|
||||||
|
Resource::new(RefCell::new(None))
|
||||||
|
};
|
||||||
|
|
||||||
|
static LOCAL: Local<i32, Exti0> = Local::new(0);
|
||||||
|
|
||||||
|
fn t1(mut task: Exti0, ref priority: P1, ref threshold: T1) {
|
||||||
|
// First run
|
||||||
|
static FIRST: Local<bool, Exti0> = Local::new(true);
|
||||||
|
|
||||||
|
let first = *FIRST.borrow(&task);
|
||||||
|
|
||||||
|
if first {
|
||||||
|
// toggle
|
||||||
|
*FIRST.borrow_mut(&mut task) = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if first {
|
||||||
|
threshold.raise(
|
||||||
|
&CHANNEL, move |threshold| {
|
||||||
|
let channel = CHANNEL.access(priority, threshold);
|
||||||
|
|
||||||
|
// BAD: give up task token
|
||||||
|
*channel.borrow_mut() = Some(task);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let _local = LOCAL.borrow_mut(&mut task);
|
||||||
|
|
||||||
|
// ..
|
||||||
|
|
||||||
|
// `t2` will preempt `t1`
|
||||||
|
rtfm::request(t2);
|
||||||
|
|
||||||
|
// ..
|
||||||
|
|
||||||
|
// `LOCAL` mutably borrowed up to this point
|
||||||
|
}
|
||||||
|
|
||||||
|
fn t2(_task: Exti1, ref priority: P2, ref threshold: T2) {
|
||||||
|
let channel = CHANNEL.access(priority, threshold);
|
||||||
|
let mut channel = channel.borrow_mut();
|
||||||
|
|
||||||
|
if let Some(mut other_task) = channel.take() {
|
||||||
|
// BAD: `t2` has access to `t1`'s task token
|
||||||
|
// so it can now mutably access local while `t1` is also using it
|
||||||
|
let _local = LOCAL.borrow_mut(&mut other_task);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fake device crate
|
||||||
|
extern crate core;
|
||||||
|
extern crate cortex_m;
|
||||||
|
|
||||||
|
mod device {
|
||||||
|
pub mod interrupt {
|
||||||
|
use cortex_m::ctxt::Context;
|
||||||
|
use cortex_m::interrupt::Nr;
|
||||||
|
|
||||||
|
extern "C" fn default_handler<T>(_: T) {}
|
||||||
|
|
||||||
|
pub struct Handlers {
|
||||||
|
pub Exti0: extern "C" fn(Exti0),
|
||||||
|
pub Exti1: extern "C" fn(Exti1),
|
||||||
|
pub Exti2: extern "C" fn(Exti2),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Exti0;
|
||||||
|
pub struct Exti1;
|
||||||
|
pub struct Exti2;
|
||||||
|
|
||||||
|
pub enum Interrupt {
|
||||||
|
Exti0,
|
||||||
|
Exti1,
|
||||||
|
Exti2,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Nr for Interrupt {
|
||||||
|
fn nr(&self) -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Context for Exti0 {}
|
||||||
|
|
||||||
|
unsafe impl Nr for Exti0 {
|
||||||
|
fn nr(&self) -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl !Send for Exti0 {}
|
||||||
|
|
||||||
|
unsafe impl Context for Exti1 {}
|
||||||
|
|
||||||
|
unsafe impl Nr for Exti1 {
|
||||||
|
fn nr(&self) -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl !Send for Exti1 {}
|
||||||
|
|
||||||
|
unsafe impl Context for Exti2 {}
|
||||||
|
|
||||||
|
unsafe impl Nr for Exti2 {
|
||||||
|
fn nr(&self) -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl !Send for Exti2 {}
|
||||||
|
|
||||||
|
pub const DEFAULT_HANDLERS: Handlers = Handlers {
|
||||||
|
Exti0: default_handler,
|
||||||
|
Exti1: default_handler,
|
||||||
|
Exti2: default_handler,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue