mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
Fixed UB in generated Monotonic::now()
This commit is contained in:
parent
555f36857e
commit
1a46345a2a
3 changed files with 26 additions and 12 deletions
|
@ -112,9 +112,12 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, monotonic)| {
|
.map(|(_, monotonic)| {
|
||||||
let name = &monotonic.ident;
|
let name = &monotonic.ident;
|
||||||
|
let name_str = &name.to_string();
|
||||||
let ty = &monotonic.ty;
|
let ty = &monotonic.ty;
|
||||||
let mangled_name = util::mangle_monotonic_type(&name.to_string());
|
let mangled_name = util::mangle_monotonic_type(&name_str);
|
||||||
let ident = util::monotonic_ident(&name.to_string());
|
let ident = util::monotonic_ident(&name_str);
|
||||||
|
let panic_str = &format!("Use of monotonic '{}' before it was passed to the runtime", name_str);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub use rtic::Monotonic as _;
|
pub use rtic::Monotonic as _;
|
||||||
|
|
||||||
|
@ -123,14 +126,20 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod #name {
|
pub mod #name {
|
||||||
|
/// Access the global `Monotonic` implementation, not that this will panic
|
||||||
|
/// before the this `Monotonic` has been passed to the RTIC runtime.
|
||||||
pub fn now() -> rtic::time::Instant<#app_path::#mangled_name> {
|
pub fn now() -> rtic::time::Instant<#app_path::#mangled_name> {
|
||||||
rtic::export::interrupt::free(|_| {
|
rtic::export::interrupt::free(|_| {
|
||||||
use rtic::Monotonic as _;
|
use rtic::Monotonic as _;
|
||||||
use rtic::time::Clock as _;
|
use rtic::time::Clock as _;
|
||||||
if let Ok(v) = unsafe{ (&*#app_path::#ident.as_ptr()).try_now() } {
|
if let Some(m) = unsafe{ #app_path::#ident.as_ref() } {
|
||||||
v
|
if let Ok(v) = m.try_now() {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
unreachable!("Your monotonic is not infallible!")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!("Your monotonic is not infallible!")
|
panic!(#panic_str);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
|
|
||||||
// Store the monotonic
|
// Store the monotonic
|
||||||
let name = util::monotonic_ident(&monotonic.to_string());
|
let name = util::monotonic_ident(&monotonic.to_string());
|
||||||
stmts.push(quote!(#name.as_mut_ptr().write(monotonics.#idx);));
|
stmts.push(quote!(#name = Some(monotonics.#idx);));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable the interrupts -- this completes the `init`-ialization phase
|
// Enable the interrupts -- this completes the `init`-ialization phase
|
||||||
|
|
|
@ -69,11 +69,11 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
|
|
||||||
let mono = util::monotonic_ident(&monotonic_name);
|
let mono = util::monotonic_ident(&monotonic_name);
|
||||||
let doc = &format!("Storage for {}", monotonic_name);
|
let doc = &format!("Storage for {}", monotonic_name);
|
||||||
let mono_ty = quote!(core::mem::MaybeUninit<#m>);
|
let mono_ty = quote!(Option<#m>);
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
static mut #mono: #mono_ty = core::mem::MaybeUninit::uninit();
|
static mut #mono: #mono_ty = None;
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +122,15 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe fn #bound_interrupt() {
|
unsafe fn #bound_interrupt() {
|
||||||
while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue(
|
|
||||||
|| #disable_isr,
|
while let Some((task, index)) = rtic::export::interrupt::free(|_|
|
||||||
&mut *#app_path::#m_ident.as_mut_ptr(),
|
if let Some(mono) = #app_path::#m_ident.as_mut() {
|
||||||
))
|
#tq.dequeue(|| #disable_isr, mono)
|
||||||
|
} else {
|
||||||
|
// We can only use the timer queue if `init` has returned, and it
|
||||||
|
// writes the `Some(monotonic)` we are accessing here.
|
||||||
|
core::hint::unreachable_unchecked()
|
||||||
|
})
|
||||||
{
|
{
|
||||||
match task {
|
match task {
|
||||||
#(#arms)*
|
#(#arms)*
|
||||||
|
|
Loading…
Reference in a new issue