Skip to content

fix edition 2024 unsafe link section #1055

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rtic-macros/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
## [Unreleased]

- Unstable support for ESP32-C6
- Fix: supoort edition 2024 `unsafe(link_section)` attribute
- Adapt `slic` backends to new version with `mecall`
- Allow software tasks to be diverging (return `!`) and give them `'static` context.

Expand Down
17 changes: 13 additions & 4 deletions rtic-macros/src/codegen/local_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@ pub fn codegen(app: &App, _analysis: &Analysis) -> TokenStream2 {

// late resources in `util::link_section_uninit`
// unless user specifies custom link section
let section = if attrs
.iter()
.any(|attr| attr.path().is_ident("link_section"))
{
let section = if attrs.iter().any(|attr| {
let is_link_section = attr.path().is_ident("link_section");
let is_unsafe = attr.path().is_ident("unsafe");
let is_embedded_link_section = match attr.parse_args() {
Ok(syn::Expr::Assign(assign)) => match &*assign.left {
syn::Expr::Path(path) => path.path.is_ident("link_section"),
_ => false,
},
_ => false,
};

is_link_section || (is_unsafe && is_embedded_link_section)
}) {
None
} else {
Some(util::link_section_uninit())
Expand Down
17 changes: 13 additions & 4 deletions rtic-macros/src/codegen/shared_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {

// late resources in `util::link_section_uninit`
// unless user specifies custom link section
let section = if attrs
.iter()
.any(|attr| attr.path().is_ident("link_section"))
{
let section = if attrs.iter().any(|attr| {
let is_link_section = attr.path().is_ident("link_section");
let is_unsafe = attr.path().is_ident("unsafe");
let is_embedded_link_section = match attr.parse_args() {
Ok(syn::Expr::Assign(assign)) => match &*assign.left {
syn::Expr::Path(path) => path.path.is_ident("link_section"),
_ => false,
},
_ => false,
};

is_link_section || (is_unsafe && is_embedded_link_section)
}) {
None
} else {
Some(util::link_section_uninit())
Expand Down
1 change: 1 addition & 0 deletions rtic/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Example:
- Placate clippy
- Updated esp32c3 dependency to v0.27.0
- Allow software tasks to be diverging (return `!`) and give them `'static` context.
- Added more `unsafe` blocks and migrated to 2024 edition.

### Added

Expand Down
2 changes: 1 addition & 1 deletion rtic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ authors = [
categories = ["concurrency", "embedded", "no-std", "asynchronous"]
description = "Real-Time Interrupt-driven Concurrency (RTIC): a concurrency framework for building real-time systems"
documentation = "https://rtic.rs/"
edition = "2021"
edition = "2024"
keywords = ["embedded", "async", "runtime", "no-std", "rtos"]
license = "MIT OR Apache-2.0"
name = "rtic"
Expand Down
22 changes: 12 additions & 10 deletions rtic/src/export/cortex_basepri.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::cortex_logical2hw;
use cortex_m::register::{basepri, basepri_max};
pub use cortex_m::{
Peripherals,
asm::wfi,
interrupt,
peripheral::{scb::SystemHandler, DWT, SCB, SYST},
Peripherals,
peripheral::{DWT, SCB, SYST, scb::SystemHandler},
};

#[cfg(not(any(feature = "thumbv7-backend", feature = "thumbv8main-backend")))]
Expand Down Expand Up @@ -69,13 +69,15 @@ pub unsafe fn lock<T, R>(
nvic_prio_bits: u8,
f: impl FnOnce(&mut T) -> R,
) -> R {
if ceiling == (1 << nvic_prio_bits) {
critical_section::with(|_| f(&mut *ptr))
} else {
let current = basepri::read();
basepri_max::write(cortex_logical2hw(ceiling, nvic_prio_bits));
let r = f(&mut *ptr);
basepri::write(current);
r
unsafe {
if ceiling == (1 << nvic_prio_bits) {
critical_section::with(|_| f(&mut *ptr))
} else {
let current = basepri::read();
basepri_max::write(cortex_logical2hw(ceiling, nvic_prio_bits));
let r = f(&mut *ptr);
basepri::write(current);
r
}
}
}
58 changes: 33 additions & 25 deletions rtic/src/export/cortex_source_mask.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pub use cortex_m::{
Peripherals,
asm::wfi,
interrupt,
peripheral::{scb::SystemHandler, DWT, NVIC, SCB, SYST},
Peripherals,
peripheral::{DWT, NVIC, SCB, SYST, scb::SystemHandler},
};

#[cfg(not(any(feature = "thumbv6-backend", feature = "thumbv8base-backend")))]
Expand Down Expand Up @@ -57,7 +57,9 @@ impl<const M: usize> Mask<M> {
let block = bit / 32;

if block as usize >= M {
panic!("Generating masks for thumbv6/thumbv8m.base failed! Are you compiling for thumbv6 on an thumbv7 MCU or using an unsupported thumbv8m.base MCU?");
panic!(
"Generating masks for thumbv6/thumbv8m.base failed! Are you compiling for thumbv6 on an thumbv7 MCU or using an unsupported thumbv8m.base MCU?"
);
}

let offset = bit - (block * 32);
Expand Down Expand Up @@ -125,25 +127,27 @@ pub unsafe fn lock<T, R, const M: usize>(
masks: &[Mask<M>; 3],
f: impl FnOnce(&mut T) -> R,
) -> R {
if ceiling >= 4 {
// safe to manipulate outside critical section
// execute closure under protection of raised system ceiling

// safe to manipulate outside critical section
critical_section::with(|_| f(&mut *ptr))
} else {
// safe to manipulate outside critical section
let mask = compute_mask(0, ceiling, masks);
let old_mask = read_mask(mask);
clear_enable_mask(mask);

// execute closure under protection of raised system ceiling
let r = f(&mut *ptr);

set_enable_mask(mask, old_mask);

// safe to manipulate outside critical section
r
unsafe {
if ceiling >= 4 {
// safe to manipulate outside critical section
// execute closure under protection of raised system ceiling

// safe to manipulate outside critical section
critical_section::with(|_| f(&mut *ptr))
} else {
// safe to manipulate outside critical section
let mask = compute_mask(0, ceiling, masks);
let old_mask = read_mask(mask);
clear_enable_mask(mask);

// execute closure under protection of raised system ceiling
let r = f(&mut *ptr);

set_enable_mask(mask, old_mask);

// safe to manipulate outside critical section
r
}
}
}

Expand Down Expand Up @@ -185,7 +189,7 @@ unsafe fn read_mask<const M: usize>(mask: Mask<M>) -> Mask<M> {
for i in 0..M {
// This check should involve compile time constants and be optimized out.
if mask.0[i] != 0 {
out.0[i] = (*NVIC::PTR).iser[i].read();
out.0[i] = unsafe { (*NVIC::PTR).iser[i].read() };
}
}

Expand All @@ -198,7 +202,9 @@ unsafe fn set_enable_mask<const M: usize>(mask: Mask<M>, old_mask: Mask<M>) {
for i in 0..M {
// This check should involve compile time constants and be optimized out.
if mask.0[i] != 0 {
(*NVIC::PTR).iser[i].write(old_mask.0[i]);
unsafe {
(*NVIC::PTR).iser[i].write(old_mask.0[i]);
}
}
}
}
Expand All @@ -209,7 +215,9 @@ unsafe fn clear_enable_mask<const M: usize>(mask: Mask<M>) {
for i in 0..M {
// This check should involve compile time constants and be optimized out.
if mask.0[i] != 0 {
(*NVIC::PTR).icer[i].write(mask.0[i]);
unsafe {
(*NVIC::PTR).icer[i].write(mask.0[i]);
}
}
}
}
4 changes: 2 additions & 2 deletions rtic/src/export/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ unsafe fn waker_clone(p: *const ()) -> RawWaker {
unsafe fn waker_wake(p: *const ()) {
// The only thing we need from a waker is the function to call to pend the async
// dispatcher.
let f: fn() = mem::transmute(p);
let f: fn() = unsafe { mem::transmute(p) };
f();
}

Expand Down Expand Up @@ -81,7 +81,7 @@ macro_rules! from_ptr_n_args {
($name:ident, $($t:ident),*) => {
#[inline(always)]
pub unsafe fn $name<$($t,)* Fun: Fn($($t,)*) -> F>(_f: Fun, ptr: &AsyncTaskExecutorPtr) -> &Self {
&*(ptr.get() as *const _)
unsafe { &*(ptr.get() as *const _) }
}
};
}
Expand Down
51 changes: 24 additions & 27 deletions rtic/src/export/riscv_esp32c3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,24 @@ pub fn run<F>(priority: u8, f: F)
where
F: FnOnce(),
{
if priority == 1 {
//if priority is 1, priority thresh should be 1
f();
unsafe {
unsafe {
if priority == 1 {
//if priority is 1, priority thresh should be 1
f();

(*INTERRUPT_CORE0::ptr())
.cpu_int_thresh()
.write(|w| w.cpu_int_thresh().bits(1));
}
} else {
//read current thresh
let initial = unsafe {
(*INTERRUPT_CORE0::ptr())
} else {
//read current thresh
let initial = (*INTERRUPT_CORE0::ptr())
.cpu_int_thresh()
.read()
.cpu_int_thresh()
.bits()
};
f();
//write back old thresh
unsafe {
.bits();
f();
//write back old thresh

(*INTERRUPT_CORE0::ptr())
.cpu_int_thresh()
.write(|w| w.cpu_int_thresh().bits(initial));
Expand All @@ -55,30 +53,29 @@ where
/// priority is current priority >= ceiling.
#[inline(always)]
pub unsafe fn lock<T, R>(ptr: *mut T, ceiling: u8, f: impl FnOnce(&mut T) -> R) -> R {
if ceiling == (15) {
//turn off interrupts completely, were at max prio
critical_section::with(|_| f(&mut *ptr))
} else {
let current = unsafe {
(*INTERRUPT_CORE0::ptr())
unsafe {
if ceiling == (15) {
//turn off interrupts completely, were at max prio
critical_section::with(|_| f(&mut *ptr))
} else {
let current = (*INTERRUPT_CORE0::ptr())
.cpu_int_thresh()
.read()
.cpu_int_thresh()
.bits()
};
.bits();

unsafe {
(*INTERRUPT_CORE0::ptr())
.cpu_int_thresh()
.write(|w| w.cpu_int_thresh().bits(ceiling + 1));
} //esp32c3 lets interrupts with prio equal to threshold through so we up it by one
let r = f(&mut *ptr);
unsafe {
//esp32c3 lets interrupts with prio equal to threshold through so we up it by one
let r = f(&mut *ptr);

(*INTERRUPT_CORE0::ptr())
.cpu_int_thresh()
.write(|w| w.cpu_int_thresh().bits(current));

r
}
r
}
}

Expand Down
Loading
Loading