aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rtic/CHANGELOG.md1
-rw-r--r--rtic/ci/expected/prio-inversion.run6
-rw-r--r--rtic/examples/prio-inversion.rs87
-rw-r--r--rtic/src/export/cortex_basepri.rs4
4 files changed, 96 insertions, 2 deletions
diff --git a/rtic/CHANGELOG.md b/rtic/CHANGELOG.md
index 815b1bb..83c2b19 100644
--- a/rtic/CHANGELOG.md
+++ b/rtic/CHANGELOG.md
@@ -13,6 +13,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
### Fixed
+- **Soundness fix:** `thumbv7` was subject to priority inversion.
- **Soundness fix:** Monotonics did not wait long enough in `Duration` based delays.
This is not directly a change for `rtic`, but required bumping the minimal version of `rtic-monotonics`.
diff --git a/rtic/ci/expected/prio-inversion.run b/rtic/ci/expected/prio-inversion.run
new file mode 100644
index 0000000..9191436
--- /dev/null
+++ b/rtic/ci/expected/prio-inversion.run
@@ -0,0 +1,6 @@
+foo - start
+pre baz spawn 0 0
+post baz spawn 0 0
+ baz - start
+ baz - end
+foo - end
diff --git a/rtic/examples/prio-inversion.rs b/rtic/examples/prio-inversion.rs
new file mode 100644
index 0000000..1c2f7fd
--- /dev/null
+++ b/rtic/examples/prio-inversion.rs
@@ -0,0 +1,87 @@
+//! examples/prio-inversion.rs
+//!
+//! Here we test to make sure we don't have priority inversion.
+
+#![no_main]
+#![no_std]
+#![deny(warnings)]
+#![deny(unsafe_code)]
+#![deny(missing_docs)]
+#![feature(type_alias_impl_trait)]
+
+use panic_semihosting as _;
+use rtic::app;
+
+// t1 p1 use b, a
+// t2 p2 use a
+// t3 p3
+// t4 p4 use b
+//
+// so t1 start , take b take a, pend t3
+// t3 should not start
+// try to see if it starts, IT SHOULD NOT
+
+#[app(device = lm3s6965, dispatchers = [SSI0, QEI0, GPIOA, GPIOB])]
+mod app {
+ use cortex_m_semihosting::{debug, hprintln};
+
+ #[shared]
+ struct Shared {
+ a: u32,
+ b: u32,
+ }
+
+ #[local]
+ struct Local {}
+
+ #[init]
+ fn init(_: init::Context) -> (Shared, Local) {
+ foo::spawn().unwrap();
+
+ (Shared { a: 0, b: 0 }, Local {})
+ }
+
+ #[task(priority = 1, shared = [a, b])]
+ async fn foo(cx: foo::Context) {
+ let foo::SharedResources { mut a, mut b, .. } = cx.shared;
+
+ hprintln!("foo - start");
+
+ // basepri = 0
+ b.lock(|b| {
+ // basepri = max(basepri = 0, ceil(b) = 4) = 4
+ a.lock(|a| {
+ // basepri = max(basepri = 4, ceil(a) = 2) = 4
+
+ hprintln!("pre baz spawn {} {}", a, b);
+
+ // This spawn should be blocked as prio(baz) = 3
+ baz::spawn().unwrap();
+
+ hprintln!("post baz spawn {} {}", a, b);
+ });
+ // basepri = 4
+ });
+ // basepri = 0
+
+ hprintln!("foo - end");
+ debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
+ }
+
+ #[task(priority = 2, shared = [a])]
+ async fn bar(_: bar::Context) {
+ hprintln!(" bar");
+ }
+
+ #[task(priority = 3)]
+ async fn baz(_: baz::Context) {
+ hprintln!(" baz - start");
+ hprintln!(" baz - end");
+ }
+
+ #[task(priority = 4, shared = [b])]
+ async fn pow(_: pow::Context) {
+ hprintln!(" pow - start");
+ hprintln!(" pow - end");
+ }
+}
diff --git a/rtic/src/export/cortex_basepri.rs b/rtic/src/export/cortex_basepri.rs
index 1401754..8aaa2d4 100644
--- a/rtic/src/export/cortex_basepri.rs
+++ b/rtic/src/export/cortex_basepri.rs
@@ -1,5 +1,5 @@
use super::cortex_logical2hw;
-use cortex_m::register::basepri;
+use cortex_m::register::{basepri, basepri_max};
pub use cortex_m::{
asm::wfi,
interrupt,
@@ -73,7 +73,7 @@ pub unsafe fn lock<T, R>(
critical_section::with(|_| f(&mut *ptr))
} else {
let current = basepri::read();
- basepri::write(cortex_logical2hw(ceiling, nvic_prio_bits));
+ basepri_max::write(cortex_logical2hw(ceiling, nvic_prio_bits));
let r = f(&mut *ptr);
basepri::write(current);
r