diff options
Diffstat (limited to 'macros/src')
-rw-r--r-- | macros/src/analyze.rs | 36 | ||||
-rw-r--r-- | macros/src/codegen.rs | 68 |
2 files changed, 74 insertions, 30 deletions
diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index 04b462fa..869b5d20 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -30,13 +30,14 @@ pub struct Analysis { pub enum Ownership { // NOTE priorities and ceilings are "logical" (0 = lowest priority, 255 = highest priority) Owned { priority: u8 }, + CoOwned { priority: u8 }, Shared { ceiling: u8 }, } impl Ownership { pub fn needs_lock(&self, priority: u8) -> bool { match *self { - Ownership::Owned { .. } => false, + Ownership::Owned { .. } | Ownership::CoOwned { .. } => false, Ownership::Shared { ceiling } => { debug_assert!(ceiling >= priority); @@ -44,6 +45,13 @@ impl Ownership { } } } + + pub fn is_owned(&self) -> bool { + match *self { + Ownership::Owned { .. } => true, + _ => false, + } + } } pub struct Dispatcher { @@ -72,18 +80,24 @@ pub fn app(app: &App) -> Analysis { for (priority, res) in app.resource_accesses() { if let Some(ownership) = ownerships.get_mut(res) { match *ownership { - Ownership::Owned { priority: ceiling } | Ownership::Shared { ceiling } => { - if priority != ceiling { - *ownership = Ownership::Shared { - ceiling: cmp::max(ceiling, priority), - }; - - let res = &app.resources[res]; - if res.mutability.is_none() { - assert_sync.insert(res.ty.clone()); - } + Ownership::Owned { priority: ceiling } + | Ownership::CoOwned { priority: ceiling } + | Ownership::Shared { ceiling } + if priority != ceiling => + { + *ownership = Ownership::Shared { + ceiling: cmp::max(ceiling, priority), + }; + + let res = &app.resources[res]; + if res.mutability.is_none() { + assert_sync.insert(res.ty.clone()); } } + Ownership::Owned { priority: ceiling } if ceiling == priority => { + *ownership = Ownership::CoOwned { priority }; + } + _ => {} } continue; diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index ff1062ae..6d01d32d 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -676,6 +676,7 @@ fn prelude( } } else { let ownership = &analysis.ownerships[name]; + let mut exclusive = false; if ownership.needs_lock(logical_prio) { may_call_lock = true; @@ -710,28 +711,53 @@ fn prelude( exprs.push(quote!(#name: <#name as owned_singleton::Singleton>::new())); } else { needs_unsafe = true; - defs.push(quote!(pub #name: &'a mut #name)); - exprs.push( - quote!(#name: &mut <#name as owned_singleton::Singleton>::new()), - ); + if ownership.is_owned() { + defs.push(quote!(pub #name: &'a mut #name)); + exprs.push(quote!( + #name: &mut <#name as owned_singleton::Singleton>::new() + )); + } else { + may_call_lock = true; + defs.push(quote!(pub #name: rtfm::Exclusive<'a, #name>)); + exprs.push(quote!( + #name: rtfm::Exclusive( + &mut <#name as owned_singleton::Singleton>::new() + ) + )); + } } continue; } else { - defs.push(quote!(pub #name: &#lt #mut_ #ty)); + if ownership.is_owned() || mut_.is_none() { + defs.push(quote!(pub #name: &#lt #mut_ #ty)); + } else { + exclusive = true; + may_call_lock = true; + defs.push(quote!(pub #name: rtfm::Exclusive<#lt, #ty>)); + } } } let alias = &ctxt.statics[name]; needs_unsafe = true; if initialized { - exprs.push(quote!(#name: &#mut_ #alias)); + if exclusive { + exprs.push(quote!(#name: rtfm::Exclusive(&mut #alias))); + } else { + exprs.push(quote!(#name: &#mut_ #alias)); + } } else { let method = if mut_.is_some() { quote!(get_mut) } else { quote!(get_ref) }; - exprs.push(quote!(#name: #alias.#method() )); + + if exclusive { + exprs.push(quote!(#name: rtfm::Exclusive(#alias.#method()) )); + } else { + exprs.push(quote!(#name: #alias.#method() )); + } } } } @@ -1655,19 +1681,23 @@ fn mk_resource( }; items.push(quote!( - unsafe impl<'a> rtfm::Mutex for #path<'a> { - const CEILING: u8 = #ceiling; - const NVIC_PRIO_BITS: u8 = #device::NVIC_PRIO_BITS; - type Data = #ty; + impl<'a> rtfm::Mutex for #path<'a> { + type T = #ty; - #[inline(always)] - unsafe fn priority(&self) -> &core::cell::Cell<u8> { - &self.#priority - } - - #[inline(always)] - fn ptr(&self) -> *mut Self::Data { - unsafe { #ptr } + #[inline] + fn lock<R, F>(&mut self, f: F) -> R + where + F: FnOnce(&mut Self::T) -> R, + { + unsafe { + rtfm::export::claim( + #ptr, + &self.#priority, + #ceiling, + #device::NVIC_PRIO_BITS, + f, + ) + } } } )); |