fix: make mutexes !Send

Each mutex is generated uniquely for each task, it is unsound to send
them between tasks. But they are `Send`. Before, it wasn't an issue,
because you couldn't share non-`'static` data between them, but with
\#1043 you can make the mutex `'static`. Thus we need to use actual
tools that Rust provides and out out from `Send`.

Currently, mutexes are simple ZSTs with `PhantomData<&'a ()>`, which is `Send`.
We replace it with `PhantomData<(&'a (), *const u8)>`, and return `Sync`
back via `unsafe` implementation. It is trivially sound, because mutexes have
no method methods that accept `&self`.

See https://doc.rust-lang.org/std/sync/struct.Exclusive.html for details.
This commit is contained in:
Oleksandr Babak 2025-10-28 13:58:18 +01:00
parent dbc5d3ceca
commit 3d0ced0bd1
No known key found for this signature in database
GPG key ID: B21CA2CAC0240BB9

View file

@ -62,9 +62,14 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
#[allow(non_camel_case_types)]
#(#cfgs)*
pub struct #shared_name<'a> {
__rtic_internal_p: ::core::marker::PhantomData<&'a ()>,
__rtic_internal_p: ::core::marker::PhantomData<(&'a (), *const u8)>,
}
// Opt out from `Send`.
// `#shared_name` is trivially `Sync` because there are no `&self` methods.
// See https://doc.rust-lang.org/std/sync/struct.Exclusive.html .
unsafe impl<'a> Sync for #shared_name<'a> {}
#(#cfgs)*
impl<'a> #shared_name<'a> {
#[inline(always)]