Skip to content

Commit

Permalink
macros: Don't use Option in singleton!()
Browse files Browse the repository at this point in the history
As detailed in rust-embedded#364, niche optimization of the
`Option` used in the `singleton!()` macro can lead to the initial value
of the static to contain non-zero bits.  This in turn leads to the whole
static being moved from `.bss` to `.data` which means it eats up flash
space for no reason.  Especially if the singleton stores a particularly
large type, this can be quite problematic.

Prevent this by using an explicit boolean flag instead of the `Option`
type.  This is not quite as nice but at least there is no chance for the
`singleton!()` to end up in `.data`...
  • Loading branch information
Rahix committed Jan 3, 2022
1 parent 19125ac commit a02bce1
Showing 1 changed file with 6 additions and 8 deletions.
14 changes: 6 additions & 8 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,21 @@ macro_rules! iprintln {
macro_rules! singleton {
($name:ident: $ty:ty = $expr:expr) => {
$crate::interrupt::free(|_| {
static mut $name: Option<$ty> = None;
static mut $name: (::core::mem::MaybeUninit<$ty>, bool) =
(::core::mem::MaybeUninit::uninit(), false);

#[allow(unsafe_code)]
let used = unsafe { $name.is_some() };
let used = unsafe { $name.1 };
if used {
None
} else {
let expr = $expr;

#[allow(unsafe_code)]
unsafe {
$name = Some(expr)
}

#[allow(unsafe_code)]
unsafe {
$name.as_mut()
$name.1 = true;
$name.0 = ::core::mem::MaybeUninit::new(expr);
Some(&mut *$name.0.as_mut_ptr())
}
}
})
Expand Down

1 comment on commit a02bce1

@therealprof
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet!

Please sign in to comment.