mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 15:04:32 +01:00
goodby static mut, welcome back to UnsafeCell
This commit is contained in:
parent
3c86d713a6
commit
db1574bf6b
5 changed files with 108 additions and 12 deletions
25
examples/minimal_early_resource.rs
Normal file
25
examples/minimal_early_resource.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
//! examples/idle.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
resource_x: u32,
|
||||
}
|
||||
|
||||
#[idle(resources = [resource_x])]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
29
examples/minimal_late_resource.rs
Normal file
29
examples/minimal_late_resource.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
//! examples/minimal_late_resource.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
resource_x: u32,
|
||||
}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
|
||||
(init::LateResources { resource_x: 0 }, init::Monotonics {})
|
||||
}
|
||||
|
||||
#[idle(resources = [resource_x])]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,10 +17,14 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
|||
// If it's live
|
||||
let cfgs = app.late_resources[name].cfgs.clone();
|
||||
if analysis.locations.get(name).is_some() {
|
||||
// Need to also include the cfgs
|
||||
stmts.push(quote!(
|
||||
#(#cfgs)*
|
||||
#mangled_name.as_mut_ptr().write(late.#name);
|
||||
// We include the cfgs
|
||||
#(#cfgs)*
|
||||
// Late resource is a RacyCell<MaybeUninit<T>>
|
||||
// - `get_mut_unchecked` to obtain `MaybeUninit<T>`
|
||||
// - `as_mut_ptr` to obtain a raw pointer to `MaybeUninit<T>`
|
||||
// - `write` the defined value for the late resource T
|
||||
#mangled_name.get_mut_unchecked().as_mut_ptr().write(late.#name);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,20 @@ use rtic_syntax::{analyze::Ownership, ast::App};
|
|||
|
||||
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
||||
|
||||
/// Generates `static [mut]` variables and resource proxies
|
||||
/// Generates `static` variables and resource proxies
|
||||
/// Early resources are stored in `RacyCell<T>`
|
||||
/// Late resource are stored in `RacyCell<MaybeUninit<T>>`
|
||||
///
|
||||
/// Safety:
|
||||
/// - RacyCell<T> access is `unsafe`.
|
||||
/// - RacyCell<MaybeUninit> is always written to before user access, thus
|
||||
// the generated code for user access can safely `assume_init`.
|
||||
pub fn codegen(
|
||||
app: &App,
|
||||
analysis: &Analysis,
|
||||
extra: &Extra,
|
||||
) -> (
|
||||
// mod_app -- the `static [mut]` variables behind the proxies
|
||||
// mod_app -- the `static` variables behind the proxies
|
||||
Vec<TokenStream2>,
|
||||
// mod_resources -- the `resources` module
|
||||
TokenStream2,
|
||||
|
@ -24,18 +31,26 @@ pub fn codegen(
|
|||
let mangled_name = util::mark_internal_ident(&name);
|
||||
|
||||
{
|
||||
// TODO: do we really need this in the single core case
|
||||
// late resources in `util::link_section_uninit`
|
||||
let section = if expr.is_none() {
|
||||
util::link_section_uninit(true)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// resource type and assigned value
|
||||
let (ty, expr) = if let Some(expr) = expr {
|
||||
(quote!(#ty), quote!(#expr))
|
||||
} else {
|
||||
// early resource
|
||||
(
|
||||
quote!(core::mem::MaybeUninit<#ty>),
|
||||
quote!(core::mem::MaybeUninit::uninit()),
|
||||
quote!(rtic::RacyCell<#ty>),
|
||||
quote!(rtic::RacyCell::new(#expr)),
|
||||
)
|
||||
} else {
|
||||
// late resource
|
||||
(
|
||||
quote!(rtic::RacyCell<core::mem::MaybeUninit<#ty>>),
|
||||
quote!(rtic::RacyCell::new(core::mem::MaybeUninit::uninit())),
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -46,7 +61,7 @@ pub fn codegen(
|
|||
#(#attrs)*
|
||||
#(#cfgs)*
|
||||
#section
|
||||
static mut #mangled_name: #ty = #expr;
|
||||
static #mangled_name: #ty = #expr;
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -74,14 +89,16 @@ pub fn codegen(
|
|||
));
|
||||
|
||||
let ptr = if expr.is_none() {
|
||||
// late resource
|
||||
quote!(
|
||||
#(#cfgs)*
|
||||
#mangled_name.as_mut_ptr()
|
||||
&mut #mangled_name.get_mut_unchecked().assume_init()
|
||||
)
|
||||
} else {
|
||||
// early resource
|
||||
quote!(
|
||||
#(#cfgs)*
|
||||
&mut #mangled_name
|
||||
unsafe { #mangled_name.get_mut_unchecked() }
|
||||
)
|
||||
};
|
||||
|
||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -55,3 +55,24 @@ where
|
|||
{
|
||||
NVIC::pend(interrupt)
|
||||
}
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
|
||||
/// Internal replacement for `static mut T`
|
||||
// TODO: Decide name and location.
|
||||
pub struct RacyCell<T>(UnsafeCell<T>);
|
||||
|
||||
impl<T> RacyCell<T> {
|
||||
/// Create a RacyCell
|
||||
pub const fn new(value: T) -> Self {
|
||||
RacyCell(UnsafeCell::new(value))
|
||||
}
|
||||
|
||||
/// Get &mut T
|
||||
pub unsafe fn get_mut_unchecked(&self) -> &mut T {
|
||||
&mut *self.0.get()
|
||||
}
|
||||
}
|
||||
|
||||
// The type wrapped need to be Sync for RacyCell<T> to be Sync
|
||||
unsafe impl<T> Sync for RacyCell<T> where T: Sync {}
|
||||
|
|
Loading…
Reference in a new issue