book/resources: rm #[task_local] mention; add #[lock_free] example

the #[task_local] attribute was removed
This commit is contained in:
Jorge Aparicio 2021-07-22 09:17:39 +02:00
parent f9a7efb235
commit 5805a05fac
3 changed files with 85 additions and 7 deletions

View file

@ -97,11 +97,15 @@ $ cargo run --example only-shared-access
## Lock-free resource access of mutable resources
There exists two other options dealing with resources
A critical section is *not* required to access a `#[shared]` resource that's only accessed by tasks running at the *same* priority.
In this case, you can opt out of the `lock` API by adding the `#[lock_free]` field-level attribute to the resource declaration (see example below).
Note that this is merely a convenience: if you do use the `lock` API, at runtime the framework will *not* produce a critical section.
* `#[lock_free]`: there might be several tasks with the same priority
accessing the resource without critical section. Since tasks with the
same priority never can preempt another task on the same priority
this is safe.
* `#[task_local]`: there must be only one task using this resource,
similar to a `static mut` task local resource, but (optionally) set-up by init.
``` rust
{{#include ../../../../examples/lock-free.rs}}
```
``` console
$ cargo run --example lock-free
{{#include ../../../../ci/expected/lock-free.run}}
```

14
ci/expected/lock-free.run Normal file
View file

@ -0,0 +1,14 @@
GPIOA/start
GPIOA/counter = 1
GPIOA/end
GPIOB/start
GPIOB/counter = 2
GPIOB/end
GPIOA/start
GPIOA/counter = 3
GPIOA/end
GPIOB/start
GPIOB/counter = 4
GPIOB/end
GPIOA/start
GPIOA/counter = 5

60
examples/lock-free.rs Normal file
View file

@ -0,0 +1,60 @@
//! examples/lock-free.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
#[shared]
struct Shared {
#[lock_free] // <- lock-free shared resource
counter: u64,
}
#[local]
struct Local {}
#[init]
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
rtic::pend(Interrupt::GPIOA);
(Shared { counter: 0 }, Local {}, init::Monotonics())
}
#[task(binds = GPIOA, shared = [counter])] // <- same priority
fn gpioa(c: gpioa::Context) {
hprintln!("GPIOA/start").unwrap();
rtic::pend(Interrupt::GPIOB);
*c.shared.counter += 1; // <- no lock API required
let counter = *c.shared.counter;
hprintln!(" GPIOA/counter = {}", counter).unwrap();
if counter == 5 {
debug::exit(debug::EXIT_SUCCESS);
}
hprintln!("GPIOA/end").unwrap();
}
#[task(binds = GPIOB, shared = [counter])] // <- same priority
fn gpiob(c: gpiob::Context) {
hprintln!("GPIOB/start").unwrap();
rtic::pend(Interrupt::GPIOA);
*c.shared.counter += 1; // <- no lock API required
let counter = *c.shared.counter;
hprintln!(" GPIOB/counter = {}", counter).unwrap();
if counter == 5 {
debug::exit(debug::EXIT_SUCCESS);
}
hprintln!("GPIOB/end").unwrap();
}
}