mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 15:04:32 +01:00
wip tests do pass, MutexStruct based
This commit is contained in:
parent
20602bd77c
commit
b138cc1631
8 changed files with 76 additions and 40 deletions
|
@ -143,22 +143,15 @@ pub fn codegen(
|
||||||
);
|
);
|
||||||
let ident_mut = util::shared_resources_ident_mut(ctxt, app);
|
let ident_mut = util::shared_resources_ident_mut(ctxt, app);
|
||||||
|
|
||||||
let item = quote!(
|
let mut items = vec![];
|
||||||
|
items.push(quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
pub struct #ident<#lt> {
|
pub struct #ident<#lt> {
|
||||||
#(#fields,)*
|
#(#fields,)*
|
||||||
}
|
}
|
||||||
|
));
|
||||||
// Used by the lock-all API
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[doc = #doc_mut]
|
|
||||||
pub struct #ident_mut<#lt> {
|
|
||||||
#(#fields_mut,)*
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let arg = if ctxt.is_init() {
|
let arg = if ctxt.is_init() {
|
||||||
None
|
None
|
||||||
|
@ -166,7 +159,16 @@ pub fn codegen(
|
||||||
Some(quote!(priority: &#lt rtic::export::Priority))
|
Some(quote!(priority: &#lt rtic::export::Priority))
|
||||||
};
|
};
|
||||||
|
|
||||||
let (lock_all, get_prio) = if let Some(name) = field_get_prio {
|
let (lock_all, new_struct, get_prio) = if let Some(name) = field_get_prio {
|
||||||
|
items.push(quote!(
|
||||||
|
// Used by the lock-all API
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[doc = #doc_mut]
|
||||||
|
pub struct #ident_mut<#lt> {
|
||||||
|
#(#fields_mut,)*
|
||||||
|
}
|
||||||
|
));
|
||||||
(
|
(
|
||||||
util::impl_mutex_struct(
|
util::impl_mutex_struct(
|
||||||
extra,
|
extra,
|
||||||
|
@ -177,6 +179,17 @@ pub fn codegen(
|
||||||
quote!(self.priority()),
|
quote!(self.priority()),
|
||||||
quote!(|| { #ident_mut::new() }),
|
quote!(|| { #ident_mut::new() }),
|
||||||
),
|
),
|
||||||
|
quote!(
|
||||||
|
// Used by the lock-all API
|
||||||
|
impl<#lt> #ident_mut<#lt> {
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
#ident_mut {
|
||||||
|
#(#values_mut,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
quote!(
|
quote!(
|
||||||
// Used by the lock-all API
|
// Used by the lock-all API
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -186,7 +199,14 @@ pub fn codegen(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(quote!(), quote!())
|
items.push(quote!(
|
||||||
|
// Used by the lock-all API
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[doc = #doc_mut]
|
||||||
|
pub struct #ident_mut {}
|
||||||
|
));
|
||||||
|
(quote!(), quote!(), quote!())
|
||||||
};
|
};
|
||||||
|
|
||||||
let implementations = quote!(
|
let implementations = quote!(
|
||||||
|
@ -201,18 +221,10 @@ pub fn codegen(
|
||||||
#get_prio
|
#get_prio
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by the lock-all API
|
#new_struct
|
||||||
impl<#lt> #ident_mut<#lt> {
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn new() -> Self {
|
|
||||||
#ident_mut {
|
|
||||||
#(#values_mut,)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#lock_all
|
#lock_all
|
||||||
);
|
);
|
||||||
|
|
||||||
(item, implementations)
|
(quote!(#(#items)*), implementations)
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ pub fn impl_mutex_struct(
|
||||||
type T = #ty;
|
type T = #ty;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lock<RTIC_INTERNAL_R>(&mut self, f: impl FnOnce(#ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R {
|
fn lock<RTIC_INTERNAL_R>(&mut self, f: impl FnOnce(&mut #ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R {
|
||||||
/// Priority ceiling
|
/// Priority ceiling
|
||||||
const CEILING: u8 = #ceiling;
|
const CEILING: u8 = #ceiling;
|
||||||
|
|
||||||
|
|
|
@ -175,26 +175,27 @@ pub unsafe fn lock_struct<T, R>(
|
||||||
priority: &Priority,
|
priority: &Priority,
|
||||||
ceiling: u8,
|
ceiling: u8,
|
||||||
nvic_prio_bits: u8,
|
nvic_prio_bits: u8,
|
||||||
f: impl FnOnce(T) -> R,
|
f: impl FnOnce(&mut T) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
let current = priority.get();
|
let current = priority.get();
|
||||||
|
|
||||||
if current < ceiling {
|
if current < ceiling {
|
||||||
if ceiling == (1 << nvic_prio_bits) {
|
if ceiling == (1 << nvic_prio_bits) {
|
||||||
priority.set(u8::max_value());
|
priority.set(u8::max_value());
|
||||||
let r = interrupt::free(|_| f(ptr()));
|
let r = interrupt::free(|_| f(&mut ptr()));
|
||||||
priority.set(current);
|
priority.set(current);
|
||||||
r
|
r
|
||||||
} else {
|
} else {
|
||||||
priority.set(ceiling);
|
priority.set(ceiling);
|
||||||
basepri::write(logical2hw(ceiling, nvic_prio_bits));
|
basepri::write(logical2hw(ceiling, nvic_prio_bits));
|
||||||
let r = f(ptr()); // inside of lock
|
let r = f(&mut ptr()); // inside of lock
|
||||||
|
cortex_m::asm::nop();
|
||||||
basepri::write(logical2hw(current, nvic_prio_bits));
|
basepri::write(logical2hw(current, nvic_prio_bits));
|
||||||
priority.set(current);
|
priority.set(current);
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f(ptr())
|
f(&mut ptr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,6 +227,34 @@ pub unsafe fn lock<T, R>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lock the resource proxy by setting the PRIMASK
|
||||||
|
/// and running the closure with interrupt::free
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Writing to the PRIMASK
|
||||||
|
/// Dereferencing a raw pointer
|
||||||
|
#[cfg(not(armv7m))]
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn lock_struct<T, R>(
|
||||||
|
ptr: impl Fn() -> T,
|
||||||
|
priority: &Priority,
|
||||||
|
ceiling: u8,
|
||||||
|
_nvic_prio_bits: u8,
|
||||||
|
f: impl FnOnce(&mut T) -> R,
|
||||||
|
) -> R {
|
||||||
|
let current = priority.get();
|
||||||
|
|
||||||
|
if current < ceiling {
|
||||||
|
priority.set(u8::max_value());
|
||||||
|
let r = interrupt::free(|_| f(&mut ptr()));
|
||||||
|
priority.set(current);
|
||||||
|
r
|
||||||
|
} else {
|
||||||
|
f(&mut ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
|
pub fn logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
|
||||||
((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits)
|
((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits)
|
||||||
|
|
|
@ -111,5 +111,5 @@ pub trait MutexStruct {
|
||||||
type T;
|
type T;
|
||||||
|
|
||||||
/// Creates a critical section and grants temporary access to the protected data
|
/// Creates a critical section and grants temporary access to the protected data
|
||||||
fn lock<R>(&mut self, f: impl FnOnce(Self::T) -> R) -> R;
|
fn lock<R>(&mut self, f: impl FnOnce(&mut Self::T) -> R) -> R;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,5 @@ error: lifetime may not live long enough
|
||||||
20 | let _ = c.shared.lock(|s| s); // lifetime
|
20 | let _ = c.shared.lock(|s| s); // lifetime
|
||||||
| -- ^ returning this value requires that `'1` must outlive `'2`
|
| -- ^ returning this value requires that `'1` must outlive `'2`
|
||||||
| ||
|
| ||
|
||||||
| |return type of closure is &'2 mut __rtic_internal_fooShared
|
| |return type of closure is &'2 mut __rtic_internal_fooShared<'_>
|
||||||
| has type `&'1 mut __rtic_internal_fooShared`
|
| has type `&'1 mut __rtic_internal_fooShared<'_>`
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
//! examples/lockall_soundness.rs
|
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
|
||||||
#![deny(warnings)]
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> ui/lockall_lifetime_destruct_field.rs:28:13
|
--> ui/lockall_lifetime_destruct_field.rs:23:13
|
||||||
|
|
|
|
||||||
27 | let _ = c.shared.lock(|foo::Shared { a }| {
|
22 | let _ = c.shared.lock(|foo::Shared { a }| {
|
||||||
| ------------------ return type of closure is &'2 mut &mut u32
|
| ------------------ return type of closure is &'2 mut &mut u32
|
||||||
| |
|
| |
|
||||||
| has type `&'1 mut __rtic_internal_fooShared`
|
| has type `&'1 mut __rtic_internal_fooShared<'_>`
|
||||||
28 | a // lifetime
|
23 | a // lifetime
|
||||||
| ^ returning this value requires that `'1` must outlive `'2`
|
| ^ returning this value requires that `'1` must outlive `'2`
|
||||||
|
|
|
@ -5,4 +5,4 @@ error: lifetime may not live long enough
|
||||||
| -- ^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
|
| -- ^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
|
||||||
| ||
|
| ||
|
||||||
| |return type of closure is &'2 mut u32
|
| |return type of closure is &'2 mut u32
|
||||||
| has type `&'1 mut __rtic_internal_fooShared`
|
| has type `&'1 mut __rtic_internal_fooShared<'_>`
|
||||||
|
|
Loading…
Reference in a new issue