From fc4cb7d472dad1ea0fa137bb116bd907efc19601 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 8 May 2017 12:05:42 -0500 Subject: [PATCH] replace the ceiling token with a preemption threshold token --- Cargo.toml | 2 +- build.rs | 51 +++-- src/lib.rs | 211 +++++++++--------- tests/cfail/access.rs | 30 +-- tests/cfail/ceiling.rs | 12 +- tests/cfail/lock.rs | 34 ++- tests/cfail/peripherals-alias-1.rs | 6 +- tests/cfail/peripherals-alias-2.rs | 6 +- tests/cfail/race-1.rs | 18 +- tests/cfail/race-2.rs | 20 +- tests/cfail/raise.rs | 24 ++ tests/cfail/tasks-p0.rs | 8 +- tests/cfail/tasks-same-handler.rs | 10 +- tests/cfail/tasks-wrong-idle.rs | 8 +- tests/cfail/tasks-wrong-init.rs | 10 +- tests/cfail/tasks-wrong-priority.rs | 8 +- tests/cfail/tasks-wrong-task.rs | 8 +- ...ng-ceiling.rs => tasks-wrong-threshold.rs} | 10 +- 18 files changed, 260 insertions(+), 216 deletions(-) create mode 100644 tests/cfail/raise.rs rename tests/cfail/{tasks-wrong-ceiling.rs => tasks-wrong-threshold.rs} (88%) diff --git a/Cargo.toml b/Cargo.toml index 33e83f7d5a..60c2eaead7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ quote = "0.3.15" syn = "0.11.10" [dependencies] -cortex-m = "0.2.4" +cortex-m = "0.2.5" static-ref = "0.1.0" typenum = "1.7.0" diff --git a/build.rs b/build.rs index e320c82815..85fff02616 100644 --- a/build.rs +++ b/build.rs @@ -39,16 +39,25 @@ fn main() { }, ); - // Ceilings + // Ceilings and thresholds for i in 0..(1 << bits) + 1 { let c = Ident::new(format!("C{}", i)); + let t = Ident::new(format!("T{}", i)); let u = Ident::new(format!("U{}", i)); let doc = format!("A ceiling of {}", i); tokens.push( quote! { #[doc = #doc] - pub type #c = C<::typenum::#u>; + pub type #c = Ceiling<::typenum::#u>; + }, + ); + + let doc = format!("A preemption threshold of {}", i); + tokens.push( + quote! { + #[doc = #doc] + pub type #t = Threshold<::typenum::#u>; }, ); } @@ -58,23 +67,21 @@ fn main() { let p = Ident::new(format!("P{}", i)); let u = Ident::new(format!("U{}", i)); - let doc = if i == 0 { - format!("A priority of 0, the lowest priority") - } else { - format!( - "A priority of {}{}", - i, - if i == (1 << bits) { - ", the highest priority" - } else { - "" - } - ) - }; + let doc = format!( + "A priority of {}{}", + i, + if i == 0 { + ", the lowest priority" + } else if i == (1 << bits) { + ", the highest priority" + } else { + "" + } + ); tokens.push( quote! { #[doc = #doc] - pub type #p = P<::typenum::#u>; + pub type #p = Priority<::typenum::#u>; }, ); } @@ -99,13 +106,21 @@ fn main() { let u = Ident::new(format!("U{}", (1 << bits))); let c = Ident::new(format!("C{}", (1 << bits))); + let p = Ident::new(format!("P{}", (1 << bits))); + let t = Ident::new(format!("T{}", (1 << bits))); tokens.push( quote! { /// Maximum ceiling - pub type CMAX = #c; + pub type CMax = #c; + + /// Maximum priority + pub type PMax = #p; + + /// Maximum preemption threshold + pub type TMax = #t; /// Maximum priority level - pub type UMAX = ::typenum::#u; + pub type UMax = ::typenum::#u; }, ); diff --git a/src/lib.rs b/src/lib.rs index 29b2886f56..5bd07e74c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,17 +14,18 @@ //! # Features //! //! - **Event triggered tasks** as the unit of concurrency. -//! - Supports prioritization of tasks and, thus, **preemptive multitasking**. +//! - Support for prioritization of tasks and, thus, **preemptive +//! multitasking**. //! - **Efficient and data race free memory sharing** through fine grained *non //! global* critical sections. //! - **Deadlock free execution**, guaranteed at compile time. //! - **Minimal scheduling overhead** as the scheduler has no "software //! component"; the hardware does all the scheduling. -//! - **Highly efficient memory usage**. All the tasks share the call stack and -//! there's no hard dependency on a dynamic allocator. +//! - **Highly efficient memory usage**. All the tasks share a single call stack +//! and there's no hard dependency on a dynamic memory allocator. //! - **All Cortex M3, M4 and M7 devices are fully supported**. M0(+) is -//! partially supported as the whole API is not available (due to missing -//! hardware features). +//! partially supported as the whole API is not available due to missing +//! hardware features. //! - The number of task priority levels is configurable at compile time through //! the `P2` (4 levels), `P3` (8 levels), etc. Cargo features. The number of //! priority levels supported by the hardware is device specific but this @@ -76,18 +77,18 @@ //! // device crate generated using svd2rust //! extern crate stm32f30x; //! -//! use rtfm::{C0, C16, P0}; +//! use rtfm::{P0, T0, TMax}; //! //! // TASKS (None in this example) //! tasks!(stm32f30x, {}); //! //! // INITIALIZATION PHASE -//! fn init(_priority: P0, _ceiling: &C16) { +//! fn init(_priority: P0, _threshold: &TMax) { //! hprintln!("INIT"); //! } //! //! // IDLE LOOP -//! fn idle(_priority: P0, _ceiling: C0) -> ! { +//! fn idle(_priority: P0, _threshold: T0) -> ! { //! hprintln!("IDLE"); //! //! // Sleep @@ -112,7 +113,8 @@ //! //! - `idle`, a never ending function that runs after `init`. //! -//! Note that both `init` and `idle` have priority 0, the lowest priority. +//! Both `init` and `idle` have a priority of 0, the lowest priority. In RTFM, +//! a higher priority value means more urgent. //! //! # One task //! @@ -127,16 +129,16 @@ //! extern crate stm32f30x; //! //! use stm32f30x::interrupt::Tim7; -//! use rtfm::{C0, C1, C16, Local, P0, P1}; +//! use rtfm::{Local, P0, P1, T0, T1, TMax}; //! //! // INITIALIZATION PHASE -//! fn init(_priority: P0, _ceiling: &C16) { +//! fn init(_priority: P0, _threshold: &TMax) { //! // Configure TIM7 for periodic interrupts //! // Configure GPIO for LED driving //! } //! //! // IDLE LOOP -//! fn idle(_priority: P0, _ceiling: C0) -> ! { +//! fn idle(_priority: P0, _threshold: T0) -> ! { //! // Sleep //! loop { //! rtfm::wfi(); @@ -152,7 +154,7 @@ //! }, //! }); //! -//! fn periodic(mut task: Tim7, _priority: P1, _ceiling: C1) { +//! fn periodic(mut task: Tim7, _priority: P1, _threshold: T1) { //! // Task local data //! static STATE: Local = Local::new(false); //! @@ -196,9 +198,7 @@ //! use core::cell::Cell; //! //! use stm32f30x::interrupt::{Tim6Dacunder, Tim7}; -//! use rtfm::{C0, C1, C16, P0, P1, Resource}; -//! -//! // omitted: `idle`, `init` +//! use rtfm::{C1, P0, P1, Resource, T0, T1, TMax}; //! //! tasks!(stm32f30x, { //! t1: Task { @@ -216,25 +216,25 @@ //! // Data shared between tasks `t1` and `t2` //! static COUNTER: Resource, C1> = Resource::new(Cell::new(0)); //! -//! fn init(priority: P0, ceiling: &C16) { +//! fn init(priority: P0, threshold: &TMax) { //! // .. //! } //! -//! fn idle(priority: P0, ceiling: C0) -> ! { +//! fn idle(priority: P0, threshold: T0) -> ! { //! // Sleep //! loop { //! rtfm::wfi(); //! } //! } //! -//! fn t1(_task: Tim6Dacunder, priority: P1, ceiling: C1) { -//! let counter = COUNTER.access(&priority, &ceiling); +//! fn t1(_task: Tim6Dacunder, priority: P1, threshold: T1) { +//! let counter = COUNTER.access(&priority, &threshold); //! //! counter.set(counter.get() + 1); //! } //! -//! fn t2(_task: Tim7, priority: P1, ceiling: C1) { -//! let counter = COUNTER.access(&priority, &ceiling); +//! fn t2(_task: Tim7, priority: P1, threshold: T1) { +//! let counter = COUNTER.access(&priority, &threshold); //! //! counter.set(counter.get() + 2); //! } @@ -272,7 +272,7 @@ //! use core::cell::Cell; //! //! use stm32f30x::interrupt::{Tim6Dacunder, Tim7}; -//! use rtfm::{C0, C1, C16, C2, P0, P1, P2, Resource}; +//! use rtfm::{C2, P0, P1, P2, Resource, T0, T1, T2, TMax}; //! //! tasks!(stm32f30x, { //! t1: Task { @@ -289,23 +289,23 @@ //! //! static COUNTER: Resource, C2> = Resource::new(Cell::new(0)); //! -//! fn init(priority: P0, ceiling: &C16) { +//! fn init(priority: P0, threshold: &TMax) { //! // .. //! } //! -//! fn idle(priority: P0, ceiling: C0) -> ! { +//! fn idle(priority: P0, threshold: T0) -> ! { //! // Sleep //! loop { //! rtfm::wfi(); //! } //! } //! -//! fn t1(_task: Tim6Dacunder, priority: P1, ceiling: C1) { +//! fn t1(_task: Tim6Dacunder, priority: P1, threshold: T1) { //! // .. //! -//! ceiling.raise( -//! &COUNTER, |ceiling: &C2| { -//! let counter = COUNTER.access(&priority, ceiling); +//! threshold.raise( +//! &COUNTER, |threshold: &T2| { +//! let counter = COUNTER.access(&priority, threshold); //! //! counter.set(counter.get() + 1); //! } @@ -314,8 +314,8 @@ //! // .. //! } //! -//! fn t2(_task: Tim7, priority: P2, ceiling: C2) { -//! let counter = COUNTER.access(&priority, &ceiling); +//! fn t2(_task: Tim7, priority: P2, threshold: T2) { +//! let counter = COUNTER.access(&priority, &threshold); //! //! counter.set(counter.get() + 2); //! } @@ -328,9 +328,10 @@ //! //! To avoid data races, `t1` must modify `COUNTER` in an atomic way; i.e. `t2` //! most not preempt `t1` while `COUNTER` is being modified. This is -//! accomplished by [`raise`](./struct.C.html#method.raise)-ing the `ceiling`. -//! This creates a critical section, denoted by a closure; for whose execution, -//! `COUNTER` is accessible but `t2` is blocked from preempting `t1`. +//! accomplished by [`raise`](./struct.C.html#method.raise)-ing the preemption +//! `threshold`. This creates a critical section, denoted by a closure; for +//! whose execution, `COUNTER` is accessible while `t2` is prevented from +//! preempting `t1`. //! //! How `t2` accesses `COUNTER` remains unchanged. Since `t1` can't preempt `t2` //! due to the differences in priority; no critical section is needed in `t2`. @@ -339,11 +340,12 @@ //! required because the ceiling must be the maximum between `P1` and `P2`. //! //! Finally, it should be noted that the critical section in `t1` will only -//! block tasks with a priority of 2 or lower. This is exactly what the ceiling -//! represents: it's the "bar" that a task priority must pass in order to be -//! able to preempt the current task / critical section. Note that a task with -//! e.g. a priority of 3 (`P3`) effectively imposes a ceiling of 3 (`C3`) -//! because only other task with a priority of 4 or greater can preempt it. +//! block tasks with a priority of 2 or lower. This is exactly what the +//! preemption threshold represents: it's the "bar" that a task priority must +//! pass in order to be able to preempt the current task / critical section. +//! Note that a task with a priority of e.g. 3 (`P3`) effectively imposes a +//! threshold of 3 (`C3`) because only a task with a priority of 4 or greater +//! can preempt it. //! //! # Peripherals as resources //! @@ -357,7 +359,7 @@ //! extern crate cortex_m_rtfm as rtfm; //! extern crate stm32f30x; //! -//! use rtfm::{C0, C16, P0, Peripheral}; +//! use rtfm::{P0, Peripheral, T0, TMax}; //! //! peripherals!(stm32f30x, { //! GPIOA: Peripheral { @@ -372,14 +374,14 @@ //! //! tasks!(stm32f30x, {}); //! -//! fn init(priority: P0, ceiling: &C16) { -//! let gpioa = GPIOA.access(&priority, &ceiling); -//! let rcc = RCC.access(&priority, &ceiling); +//! fn init(priority: P0, threshold: &TMax) { +//! let gpioa = GPIOA.access(&priority, threshold); +//! let rcc = RCC.access(&priority, threshold); //! //! // .. //! } //! -//! fn idle(_priority: P0) -> ! { +//! fn idle(_priority: P0, _threshold: T0) -> ! { //! // Sleep //! loop { //! rtfm::wfi(); @@ -491,10 +493,10 @@ pub struct Resource { data: UnsafeCell, } -impl Resource> +impl Resource> where RC: GreaterThanOrEqual, - RC: LessThanOrEqual, + RC: LessThanOrEqual, { /// Creates a new resource pub const fn new(data: T) -> Self { @@ -505,7 +507,7 @@ where } } -impl Resource> { +impl Resource> { /// Grants data race free and deadlock free access to the resource data /// /// This operation is zero cost and doesn't impose any additional blocking. @@ -516,16 +518,16 @@ impl Resource> { /// /// - The resource ceiling must be greater than or equal to the task /// priority - /// - The system ceiling must be greater than or equal to the resource + /// - The preemption threshold must be greater than or equal to the resource /// ceiling - pub fn access<'cs, TP, SC>( + pub fn access<'cs, TP, PT>( &'static self, - _priority: &P, - _current_ceiling: &'cs C, + _task_priority: &Priority, + _preemption_threshold: &'cs Threshold, ) -> Ref<'cs, T> where RC: GreaterThanOrEqual, - SC: GreaterThanOrEqual, + PT: GreaterThanOrEqual, { unsafe { Ref::new(&*self.data.get()) } } @@ -545,10 +547,10 @@ where _ceiling: PhantomData, } -impl Peripheral> +impl Peripheral> where - CEILING: GreaterThanOrEqual, - CEILING: LessThanOrEqual, + PC: GreaterThanOrEqual, + PC: LessThanOrEqual, { #[doc(hidden)] pub const unsafe fn _new(peripheral: cortex_m::peripheral::Peripheral

,) @@ -560,16 +562,16 @@ where } } -impl Peripheral> { +impl Peripheral> { /// See [Resource.access](./struct.Resource.html#method.access) - pub fn access<'cs, TP, SC>( + pub fn access<'cs, TP, PT>( &'static self, - _priority: &P, - _system_ceiling: &'cs C, + _task_priority: &Priority, + _preemption_threshold: &'cs Threshold, ) -> Ref<'cs, Periph> where - RC: GreaterThanOrEqual, - SC: GreaterThanOrEqual, + PC: GreaterThanOrEqual, + PT: GreaterThanOrEqual, { unsafe { Ref::new(&*self.peripheral.get()) } } @@ -582,17 +584,17 @@ unsafe impl Sync for Peripheral {} /// No task can preempt the execution of the closure pub fn atomic(f: F) -> R where - F: FnOnce(&CMAX) -> R, + F: FnOnce(&TMax) -> R, { let primask = ::cortex_m::register::primask::read(); ::cortex_m::interrupt::disable(); - let r = f(&C { _marker: PhantomData }); + let r = f(&Threshold { _marker: PhantomData }); // If the interrupts were active before our `disable` call, then re-enable // them. Otherwise, keep them disabled if primask.is_active() { - ::cortex_m::interrupt::enable(); + unsafe { ::cortex_m::interrupt::enable() } } r @@ -601,7 +603,7 @@ where /// Disables a `task` /// /// The task won't run even if the underlying interrupt is raised -pub fn disable(_task: fn(T, P, C)) +pub fn disable(_task: fn(T, Priority, Threshold)) where T: Context + Nr, { @@ -613,7 +615,7 @@ where } /// Enables a `task` -pub fn enable(_task: fn(T, P, C)) +pub fn enable(_task: fn(T, Priority, Threshold)) where T: Context + Nr, { @@ -644,7 +646,7 @@ pub fn logical2hw(logical: u8) -> u8 { } /// Requests the execution of a `task` -pub fn request(_task: fn(T, P, C)) +pub fn request(_task: fn(T, Priority, Threshold)) where T: Context + Nr, { @@ -671,31 +673,36 @@ where } #[doc(hidden)] -pub fn _validate_priority(_: &P) +pub fn _validate_priority(_: &Priority) where - TP: Cmp + LessThanOrEqual, + TP: Cmp + LessThanOrEqual, { } -/// A type-level ceiling -pub struct C { +/// Resource ceiling +pub struct Ceiling { + _marker: PhantomData, +} + +/// Preemption threshold +pub struct Threshold { _marker: PhantomData, } -impl C { - /// Raises the system ceiling to match the `resource` ceiling +impl Threshold { + /// Raises the preemption threshold to match the `resource` ceiling #[cfg(not(thumbv6m))] pub fn raise(&self, _resource: &'static RES, f: F) -> R where RES: ResourceLike, - RC: Cmp + Cmp + Unsigned, - F: FnOnce(&C) -> R, + RC: Cmp + Cmp + Unsigned, + F: FnOnce(&Threshold) -> R, { unsafe { let old_basepri = basepri::read(); basepri_max::write(logical2hw(RC::to_u8())); barrier!(); - let ret = f(&C { _marker: PhantomData }); + let ret = f(&Threshold { _marker: PhantomData }); barrier!(); basepri::write(old_basepri); ret @@ -703,12 +710,12 @@ impl C { } } -/// A type-level priority -pub struct P { - _marker: PhantomData, +/// Priority +pub struct Priority { + _marker: PhantomData, } -impl P +impl Priority where T: Unsigned, { @@ -726,11 +733,11 @@ pub unsafe trait ResourceLike { type Ceiling; } -unsafe impl ResourceLike for Peripheral> { - type Ceiling = RC; +unsafe impl ResourceLike for Peripheral> { + type Ceiling = PC; } -unsafe impl ResourceLike for Resource> { +unsafe impl ResourceLike for Resource> { type Ceiling = RC; } @@ -798,18 +805,22 @@ macro_rules! peripherals { /// The `$Interrupt` handlers are defined in the `$device` crate. /// /// Apart from defining the listed `$tasks`, the `init` and `idle` functions -/// must be defined as well. `init` has signature `fn(P0, &C16)`, and `idle` has -/// signature `fn(P0) -> !`. +/// must be defined as well. `init` has signature `fn(P0, &TMax)`, and `idle` +/// has signature `fn(P0) -> !`. /// /// # Example /// /// ``` ignore +/// #[feature(used)] +/// #[no_std] +/// +/// extern crate cortex_m_rt; /// #[macro_use] /// extern crate cortex_m_rtfm as rtfm; /// // device crate generated using `svd2rust` /// extern crate stm32f30x; /// -/// use rtfm::{C16, P0, P1, P2}; +/// use rtfm::{P0, P1, P2, T0, T1, T2, TMax}; /// use stm32f30x::interrupt::{Exti0, Tim7}; /// /// tasks!(stm32f30x, { @@ -825,11 +836,11 @@ macro_rules! peripherals { /// }, /// }); /// -/// fn init(priority: P0, ceiling: C16) { +/// fn init(priority: P0, threshold: &TMax) { /// // .. /// } /// -/// fn idle(priority: P0) -> ! { +/// fn idle(priority: P0, threshold: T0) -> ! { /// // Sleep /// loop { /// rtfm::wfi(); @@ -837,11 +848,11 @@ macro_rules! peripherals { /// } /// /// // NOTE signature must match the tasks! declaration -/// fn periodic(task: Tim7, priority: P1) { +/// fn periodic(task: Tim7, priority: P1, threshold: T1) { /// // .. /// } /// -/// fn button(task: Exti0, priority: P2) { +/// fn button(task: Exti0, priority: P2, threshold: T2) { /// // .. /// } /// ``` @@ -855,22 +866,22 @@ macro_rules! tasks { },)* }) => { fn main() { - $crate::atomic(|cmax| { - fn validate_signature(_: fn($crate::P0, &$crate::CMAX)) {} + $crate::atomic(|t_max| { + fn validate_signature(_: fn($crate::P0, &$crate::TMax)) {} validate_signature(init); let p0 = unsafe { ::core::mem::transmute::<_, P0>(()) }; - init(p0, cmax); + init(p0, t_max); set_priorities(); enable_tasks(); }); - fn validate_signature(_: fn($crate::P0, $crate::C0) -> !) {} + fn validate_signature(_: fn($crate::P0, $crate::T0) -> !) {} validate_signature(idle); let p0 = unsafe { ::core::mem::transmute::<_, P0>(()) }; - let c0 = unsafe { ::core::mem::transmute::<_, C0>(()) }; - idle(p0, c0); + let t0 = unsafe { ::core::mem::transmute::<_, T0>(()) }; + idle(p0, t0); fn set_priorities() { // NOTE(safe) this function runs in an interrupt free context @@ -914,17 +925,17 @@ macro_rules! tasks { ) { fn validate_signature( _: fn(::$device::interrupt::$Interrupt, - $crate::P, - $crate::C)) {} + $crate::Priority, + $crate::Threshold)) {} validate_signature(::$task); let p = unsafe { ::core::mem::transmute::<_, $crate::$P>(()) }; - let c = unsafe { + let t = unsafe { ::core::mem::transmute(()) }; $crate::_validate_priority(&p); - ::$task(task, p, c) + ::$task(task, p, t) } $task diff --git a/tests/cfail/access.rs b/tests/cfail/access.rs index 7524b068fd..b35fb371e1 100644 --- a/tests/cfail/access.rs +++ b/tests/cfail/access.rs @@ -1,6 +1,6 @@ extern crate cortex_m_rtfm as rtfm; -use rtfm::{C1, C2, C3, C4, C5, P2, Resource}; +use rtfm::{C1, C2, C3, C4, C5, P2, Resource, T2}; static R1: Resource = Resource::new(0); static R2: Resource = Resource::new(0); @@ -9,27 +9,27 @@ static R4: Resource = Resource::new(0); static R5: Resource = Resource::new(0); static R6: Resource = Resource::new(0); -fn j1(prio: P2, ceil: C2) { - ceil.raise( - &R1, |ceil| { - // NOTE SC = System Ceiling, P = task Priority +fn j1(prio: P2, thr: T2) { + thr.raise( + &R1, |thr| { + // NOTE PT = Preemption Threshold, TP = Task Priority - // CAN access a resource with ceiling RC when SC > RC - let r2 = R2.access(&prio, ceil); + // CAN access a resource with ceiling RC when PT > RC + let r2 = R2.access(&prio, thr); - // CAN access a resource with ceiling RC when SC == RC - let r3 = R3.access(&prio, ceil); + // CAN access a resource with ceiling RC when PT == RC + let r3 = R3.access(&prio, thr); - // CAN'T access a resource with ceiling RC when SC < RC - let r4 = R4.access(&prio, ceil); + // CAN'T access a resource with ceiling RC when PT < RC + let r4 = R4.access(&prio, thr); //~^ error - // CAN'T access a resource with ceiling RC when RC < P - let r5 = R5.access(&prio, ceil); + // CAN'T access a resource with ceiling RC when RC < TP + let r5 = R5.access(&prio, thr); //~^ error - // CAN access a resource with ceiling RC when RC == P - let r6 = R6.access(&prio, ceil); + // CAN access a resource with ceiling RC when RC == tP + let r6 = R6.access(&prio, thr); } ); } diff --git a/tests/cfail/ceiling.rs b/tests/cfail/ceiling.rs index d1961c93c3..118dbcf6f8 100644 --- a/tests/cfail/ceiling.rs +++ b/tests/cfail/ceiling.rs @@ -1,19 +1,19 @@ extern crate cortex_m_rtfm as rtfm; -use rtfm::{C2, C3, P0, P2, Resource}; +use rtfm::{C2, C3, P0, P2, Resource, T2}; static R1: Resource<(), C3> = Resource::new(()); -fn j1(prio: P2, ceil: C2) { - let c3 = ceil.raise( - &R1, |ceil| { +fn j1(prio: P2, thr: T2) { + let t3 = thr.raise( + &R1, |thr| { // forbidden: ceiling token can't outlive the critical section - ceil //~ error + thr //~ error } ); // Would be bad: lockless access to a resource with ceiling = 3 - let r2 = R1.access(&prio, c3); + let r2 = R1.access(&prio, t3); } fn j2(prio: P0) { diff --git a/tests/cfail/lock.rs b/tests/cfail/lock.rs index 62d3c6ef4e..64753ac1de 100644 --- a/tests/cfail/lock.rs +++ b/tests/cfail/lock.rs @@ -1,42 +1,36 @@ extern crate cortex_m_rtfm as rtfm; -use rtfm::{C16, C1, C2, C3, P1, P16, P2, P3, Resource}; +use rtfm::{CMax, C2, P1, P2, P3, PMax, Resource, T1, T2, T3, TMax}; static R1: Resource = Resource::new(0); -// You CAN'T use `raise` to lower the system ceiling -fn j1(prio: P3, ceil: C3) { - ceil.raise(&R1, |ceil| {}); - //~^ error -} - // You don't need to raise the ceiling to access a resource with ceiling equal // to the task priority. -fn j2(prio: P2, ceil: C2) { - ceil.raise(&R1, |_| {}); +fn j1(prio: P2, thr: T2) { + thr.raise(&R1, |_| {}); //~^ error // OK - let r1 = R1.access(&prio, &ceil); + let r1 = R1.access(&prio, &thr); } // You CAN access a resource with ceiling C from a task with priority P if C > P -// and you raise the ceiling first -fn j3(prio: P1, ceil: C1) { +// if you raise the preemption threshold first +fn j2(prio: P1, thr: T1) { // OK - ceil.raise(&R1, |ceil| { let r1 = R1.access(&prio, ceil); }) + thr.raise(&R1, |thr| { let r1 = R1.access(&prio, thr); }) } -static R2: Resource = Resource::new(0); +static R2: Resource = Resource::new(0); -// Tasks with priority less than P16 can't access a resource with ceiling C16 -fn j4(prio: P1, ceil: C1) { - ceil.raise(&R2, |ceil| {}); +// Tasks with priority less than P16 can't access a resource with ceiling CMax +fn j4(prio: P1, thr: T1) { + thr.raise(&R2, |thr| {}); //~^ error } -// Only tasks with priority P16 can access a resource with ceiling C16 -fn j5(prio: P16, ceil: C16) { +// Only tasks with priority P16 can directly access a resource with ceiling CMax +fn j5(prio: PMax, thr: TMax) { // OK - let r2 = R2.access(&prio, &ceil); + let r2 = R2.access(&prio, &thr); } diff --git a/tests/cfail/peripherals-alias-1.rs b/tests/cfail/peripherals-alias-1.rs index 0dfe8d102d..124f3510b8 100644 --- a/tests/cfail/peripherals-alias-1.rs +++ b/tests/cfail/peripherals-alias-1.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate cortex_m_rtfm as rtfm; -use rtfm::{C16, P0, P1}; +use rtfm::{P0, P1, T0, TMax}; use device::interrupt::Exti0; peripherals!(device, { @@ -22,9 +22,9 @@ peripherals!(device, { tasks!(device, {}); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } diff --git a/tests/cfail/peripherals-alias-2.rs b/tests/cfail/peripherals-alias-2.rs index 555cd740a2..b50931ee0a 100644 --- a/tests/cfail/peripherals-alias-2.rs +++ b/tests/cfail/peripherals-alias-2.rs @@ -6,7 +6,7 @@ #[macro_use] extern crate cortex_m_rtfm as rtfm; -use rtfm::{C0, C16, P0, P1}; +use rtfm::{P0, P1, T0, TMax}; use device::interrupt::Exti0; peripherals!(device, { @@ -28,9 +28,9 @@ mod foo { tasks!(device, {}); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } diff --git a/tests/cfail/race-1.rs b/tests/cfail/race-1.rs index 167802d22b..8d32c42e06 100644 --- a/tests/cfail/race-1.rs +++ b/tests/cfail/race-1.rs @@ -1,13 +1,13 @@ extern crate cortex_m_rtfm as rtfm; -use rtfm::{C1, C2, C3, C4, P1, P3, Resource}; +use rtfm::{C2, P1, P3, Resource, T1, T3}; static R1: Resource = Resource::new(0); -fn j1(prio: P1, ceil: C1) { - ceil.raise( - &R1, |ceil| { - let r1 = R1.access(&prio, ceil); +fn j1(prio: P1, thr: T1) { + thr.raise( + &R1, |thr| { + let r1 = R1.access(&prio, thr); // `j2` preempts this critical section rtfm::request(j2); @@ -15,12 +15,12 @@ fn j1(prio: P1, ceil: C1) { ); } -fn j2(_task: Task, prio: P3, ceil: C3) { +fn j2(_task: Task, prio: P3, thr: T3) { rtfm::atomic( - |ceil| { - // OK C2 (R1's ceiling) <= C16 (system ceiling) + |thr| { + // OK C2 (R1's ceiling) <= T16 (preemption threshold) // BAD C2 (R1's ceiling) < P3 (j2's priority) - let r1 = R1.access(&prio, &ceil); + let r1 = R1.access(&prio, &thr); //~^ error }, ); diff --git a/tests/cfail/race-2.rs b/tests/cfail/race-2.rs index 402a4835f6..f44856e0ef 100644 --- a/tests/cfail/race-2.rs +++ b/tests/cfail/race-2.rs @@ -1,14 +1,14 @@ extern crate cortex_m_rtfm as rtfm; -use rtfm::{C1, C2, C3, C4, P1, P3, Resource}; +use rtfm::{C2, C4, P1, P3, Resource, T1, T3}; static R1: Resource = Resource::new(0); static R2: Resource = Resource::new(0); -fn j1(prio: P1, ceil: C1) { - ceil.raise( - &R1, |ceil| { - let r1 = R1.access(&prio, ceil); +fn j1(prio: P1, thr: T1) { + thr.raise( + &R1, |thr| { + let r1 = R1.access(&prio, thr); // `j2` preempts this critical section rtfm::request(j2); @@ -16,12 +16,12 @@ fn j1(prio: P1, ceil: C1) { ); } -fn j2(_task: Task, prio: P3, ceil: C3) { - ceil.raise( - &R2, |ceil| { - // OK C2 (R1's ceiling) <= C4 (system ceiling) +fn j2(_task: Task, prio: P3, thr: T3) { + thr.raise( + &R2, |thr| { + // OK C2 (R1's ceiling) <= T4 (preemption threshold) // BAD C2 (R1's ceiling) < P3 (j2's priority) - let r1 = R1.access(&prio, ceil); + let r1 = R1.access(&prio, thr); //~^ error } ); diff --git a/tests/cfail/raise.rs b/tests/cfail/raise.rs new file mode 100644 index 0000000000..3d7e564721 --- /dev/null +++ b/tests/cfail/raise.rs @@ -0,0 +1,24 @@ +extern crate cortex_m_rtfm as rtfm; + +use rtfm::{C2, CMax, P1, P3, Resource, T1, T3}; + +static R1: Resource = Resource::new(0); + +// You CAN'T use `raise` to lower the preemption level +fn j1(prio: P3, thr: T3) { + thr.raise(&R1, |thr| {}); + //~^ error +} + +static R2: Resource = Resource::new(0); + +// You CAN'T `raise` the preemption level to the maximum +fn j2(prio: P1, thr: T1) { + thr.raise(&R2, |thr| {}); + //~^ error + + // Instead use `rtfm::atomic` to access a resource with ceiling C16 + rtfm::atomic(|thr| { + let r2 = R2.access(&prio, thr); + }); +} diff --git a/tests/cfail/tasks-p0.rs b/tests/cfail/tasks-p0.rs index 4034f62a44..588ac5d035 100644 --- a/tests/cfail/tasks-p0.rs +++ b/tests/cfail/tasks-p0.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate cortex_m_rtfm as rtfm; -use rtfm::{C0, C1, C16, P0, P1}; +use rtfm::{P0, P1, T0, T1, TMax}; use device::interrupt::Exti0; // WRONG: Tasks can't have a priority of 0. @@ -18,13 +18,13 @@ tasks!(device, { }, }); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } -fn j1(_task: Exti0, _prio: P1, _ceil: C1) {} +fn j1(_task: Exti0, _prio: P1, _thr: T1) {} // fake device crate extern crate core; diff --git a/tests/cfail/tasks-same-handler.rs b/tests/cfail/tasks-same-handler.rs index 1d32d58185..fdd8b063cd 100644 --- a/tests/cfail/tasks-same-handler.rs +++ b/tests/cfail/tasks-same-handler.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate cortex_m_rtfm as rtfm; -use rtfm::{C0, C1, C16, C2, P0, P1, P2}; +use rtfm::{P0, P1, P2, T0, T1, T2, TMax}; use device::interrupt::{Exti0, Exti1}; // WRONG: Two tasks mapped to the same interrupt handler @@ -22,15 +22,15 @@ tasks!(device, { }, }); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } -fn j1(_task: Exti0, _prio: P1, _ceil: C1) {} +fn j1(_task: Exti0, _prio: P1, _thr: T1) {} -fn j2(_task: Exti0, _prio: P2, _ceil: C2) {} +fn j2(_task: Exti0, _prio: P2, _thr: T2) {} // fake device crate extern crate core; diff --git a/tests/cfail/tasks-wrong-idle.rs b/tests/cfail/tasks-wrong-idle.rs index 954fd220b1..e6ff77904d 100644 --- a/tests/cfail/tasks-wrong-idle.rs +++ b/tests/cfail/tasks-wrong-idle.rs @@ -6,7 +6,7 @@ extern crate cortex_m_rtfm as rtfm; use device::interrupt::Exti0; -use rtfm::{C0, C1, C16, P0, P1}; +use rtfm::{P0, P1, T0, T1, TMax}; tasks!(device, { j1: Task { @@ -16,12 +16,12 @@ tasks!(device, { }, }); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} // WRONG. `idle` must have signature `fn(P0, C0) -> !` -fn idle(_: P0, _: C0) {} +fn idle(_: P0, _: T0) {} -fn j1(_task: Exti0, _prio: P1, _ceil: C1) {} +fn j1(_task: Exti0, _prio: P1, _thr: T1) {} // fake device crate extern crate core; diff --git a/tests/cfail/tasks-wrong-init.rs b/tests/cfail/tasks-wrong-init.rs index e9ebc6183b..d12b427d8c 100644 --- a/tests/cfail/tasks-wrong-init.rs +++ b/tests/cfail/tasks-wrong-init.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate cortex_m_rtfm as rtfm; -use rtfm::{C0, C1, C16, P0, P1}; +use rtfm::{P0, P1, T0, T1, TMax}; use device::interrupt::Exti0; tasks!(device, { @@ -16,14 +16,14 @@ tasks!(device, { }, }); -// WRONG. `init` must have signature `fn(P0, &C16)` -fn init(_: P0, _: &C1) {} +// WRONG. `init` must have signature `fn(P0, &TMax)` +fn init(_: P0, _: &T1) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } -fn j1(_task: Exti0, _prio: P1, _ceil: C1) {} +fn j1(_task: Exti0, _prio: P1, _thr: T1) {} // fake device crate extern crate core; diff --git a/tests/cfail/tasks-wrong-priority.rs b/tests/cfail/tasks-wrong-priority.rs index 01ff7df84b..4d05d6b0d0 100644 --- a/tests/cfail/tasks-wrong-priority.rs +++ b/tests/cfail/tasks-wrong-priority.rs @@ -6,7 +6,7 @@ extern crate cortex_m_rtfm as rtfm; use device::interrupt::Exti0; -use rtfm::{C0, C1, C16, C2, P0, P1, P2}; +use rtfm::{P0, P1, P2, T0, T1, T2, TMax}; tasks!(device, { j1: Task { @@ -16,14 +16,14 @@ tasks!(device, { }, }); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } // Wrong priority token. Declared P1, got P2 -fn j1(_task: Exti0, _prio: P2, _ceil: C2) {} +fn j1(_task: Exti0, _prio: P2, _thr: T2) {} // fake device crate extern crate core; diff --git a/tests/cfail/tasks-wrong-task.rs b/tests/cfail/tasks-wrong-task.rs index 5fae160aa1..026290a7da 100644 --- a/tests/cfail/tasks-wrong-task.rs +++ b/tests/cfail/tasks-wrong-task.rs @@ -6,7 +6,7 @@ extern crate cortex_m_rtfm as rtfm; use device::interrupt::{Exti0, Exti1}; -use rtfm::{C0, C1, C16, P0, P1}; +use rtfm::{P0, P1, T0, T1, TMax}; tasks!(device, { j1: Task { @@ -16,14 +16,14 @@ tasks!(device, { }, }); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } // Wrong task token. Declared Exti0, got Exti1 -fn j1(_task: Exti1, _prio: P1, _ceil: C1) {} +fn j1(_task: Exti1, _prio: P1, _thr: T1) {} // fake device crate extern crate core; diff --git a/tests/cfail/tasks-wrong-ceiling.rs b/tests/cfail/tasks-wrong-threshold.rs similarity index 88% rename from tests/cfail/tasks-wrong-ceiling.rs rename to tests/cfail/tasks-wrong-threshold.rs index 84dd133f8e..4fca734e06 100644 --- a/tests/cfail/tasks-wrong-ceiling.rs +++ b/tests/cfail/tasks-wrong-threshold.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate cortex_m_rtfm as rtfm; -use rtfm::{C0, C1, C16, C2, P0, P1}; +use rtfm::{C2, P0, P1, T0, T2, TMax}; use device::interrupt::Exti0; tasks!(device, { @@ -16,14 +16,14 @@ tasks!(device, { }, }); -fn init(_: P0, _: &C16) {} +fn init(_: P0, _: &TMax) {} -fn idle(_: P0, _: C0) -> ! { +fn idle(_: P0, _: T0) -> ! { loop {} } -// Wrong ceiling token. `prio` and `ceil` must match in levels -fn j1(_task: Exti0, _prio: P1, _ceil: C2) {} +// Wrong ceiling token. `prio` and `thr` must match in levels +fn j1(_task: Exti0, _prio: P1, _thr: T2) {} // fake device crate extern crate core;