Skip to content

Commit 4940d76

Browse files
Remove CoreSend/CoreSync from proposal
1 parent 01398a0 commit 4940d76

File tree

1 file changed

+29
-89
lines changed

1 file changed

+29
-89
lines changed

rfcs/0000-multi-core-soundness.md

Lines changed: 29 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ Change how we model multi-core MCUs in the following ways:
1212
interactions since those traits are unfit for the purpose.
1313
* Declare that `Send` is not sufficient to transfer resources between cores,
1414
since memory addresses can have different meanings on different cores.
15-
* Introduce `CoreSend` and `CoreSync` traits to the [`bare-metal`] crate.
16-
* Require multi-core PACs/HALs, frameworks and/or libraries to manually mark
17-
data that is safe to send across core boundaries.
1815
* Mutexes based on critical sections become declared sound due to the above:
1916
They can only turn `Send` data `Sync`, but neither allows cross-core
2017
interactions anymore.
18+
* Punt on how to deal with cross-core communication and data sharing for now,
19+
and leave it to the ecosystem.
2120

2221
# Motivation
2322
[motivation]: #motivation
@@ -102,59 +101,20 @@ risk of the resources changing their meaning when sent.
102101
# Detailed design
103102
[design]: #detailed-design
104103

105-
## Introduce common traits for modeling cross-core operations
106-
107-
The following trait definitions and impls will be added to [`bare-metal`]:
108-
109-
```rust
110-
/// Types that can be transferred across core boundaries.
111-
pub unsafe trait CoreSend {}
112-
113-
/// Types that can be accessed from multiple cores at once.
114-
pub unsafe trait CoreSync {}
115-
116-
unsafe impl<'a, T: CoreSync> CoreSend for &'a T {}
117-
```
118-
119-
Note that these are not auto traits. That is not just because auto traits are
120-
still an unstable feature, but also because that wouldn't be correct: As
121-
outlined in [Today's Soundness Issues][todays-issues], whether some data is safe
122-
to be sent between cores depends not just on its type contents, but also on its
123-
location in memory.
124-
125-
It is only safe to implement `CoreSync` if *all* instances of the implementing
126-
type will either be at memory locations shared by all cores, or are zero-sized.
127-
Similarly, it is only safe to implement `CoreSend` if *all* instances of the
128-
implementing type contain only data that is safe to send to another core (which
129-
moves the value in memory). Of course, the type's API must also ensure that no
130-
memory accesses to core-local memory occur (important for eg. core-local
131-
peripherals).
132-
133-
### `CoreSend`
134-
135-
It is expected that `CoreSend` will be implemented for peripherals shared
136-
between all cores in the system, and also by HAL wrappers of those peripherals,
137-
so that applications can transfer such peripherals to any core in the system.
138-
This RFC does not mandate how exactly those implementations will be written or
139-
generated. One option would be to give `svd2rust` an unsafe command line flag to
140-
generate `CoreSend` for all peripherals.
141-
142-
For example, `CoreSend` would be implemented by all peripherals of the LPC5411x,
143-
which has a Cortex-M4 and a Cortex-M0+ core sharing all non-core peripherals. It
144-
would *not* be implemented by the peripherals of the nRF5340, which has two
145-
cores that have independent peripherals (each core owns its peripherals).
104+
## Document what `Send` and `Sync` mean
146105

147-
`CoreSend` is expected to be used as a trait bound by support libraries, HALs
148-
and frameworks such as [µAMP] that provide support for multi-core processors.
149-
For example, an API could be built that consumes `CoreSend` types and passes
150-
them to the entry point of the secondary core.
106+
`Send` and `Sync` will be used only to model transfer and sharing of resources
107+
between different *execution contexts* that run with the same fixed set of
108+
global resources.
151109

152-
### `CoreSync`
110+
Here, an *execution context* is something that may execute code asynchronously
111+
from other code (so without needing to be called). For example, a *thread* or
112+
an *interrupt handler* would qualify as an *execution context*, while a
113+
single-threaded futures executor would *not* create any more *execution
114+
contexts* while it executes.
153115

154-
The `CoreSync` trait is expected to be used for sharing *data* between cores.
155-
A framework like [µAMP] could generate a controlled wrapper type around shared
156-
data placed in a known section, and have that wrapper implement `CoreSync`,
157-
allowing the application to copy references to the data between cores.
116+
Concretely (for embedded Rust), that means `Send` and `Sync` can be used to
117+
model threads in an RTOS, or interrupt handlers for bare-metal applications.
158118

159119
## `bare_metal::Mutex` is now sound
160120

@@ -175,34 +135,16 @@ In SMP apps, only a single executable is used for all cores, while each core can
175135
have a separate entry point (or another mechanism of identifying the running
176136
core). This means that all `static`s are shared by default.
177137

178-
Since defining a `static` only requires that its type is `Sync`, not `CoreSync`,
179-
this would be unsound. For example, it would allow storing a `bare_metal::Mutex`
180-
in a `static` and access it from all cores. Therefore, this RFC foregoes the
181-
ability to write safe SMP apps in Rust, instead proposing to shift focus to AMP
182-
apps, which do not share data by default and produce a separate executable per
183-
core.
138+
Since defining a `static` only requires that its type is `Sync`, this would be
139+
unsound. For example, it would allow storing a `bare_metal::Mutex` in a `static`
140+
and access it from all cores. Therefore, this RFC foregoes the ability to write
141+
safe SMP apps in Rust, instead proposing to shift focus to AMP apps, which do
142+
not share data by default and produce a separate executable per core.
184143

185144
# How We Teach This
186145
[how-we-teach-this]: #how-we-teach-this
187146

188-
API documentation of `CoreSend` and `CoreSync` needs to be clarified. The
189-
single-sentence documentation above is not meant to be complete.
190-
191-
## Document what `Send` and `Sync` mean
192-
193-
`Send` and `Sync` will be used only to model transfer and sharing of resources
194-
between different *execution contexts* that run with the same fixed set of
195-
global resources.
196-
197-
Here, an *execution context* is something that may execute code asynchronously
198-
from other code (so without needing to be called). For example, a *thread* or
199-
an *interrupt handler* would qualify as an *execution context*, while a
200-
single-threaded futures executor would *not* create any more *execution
201-
contexts* while it executes.
202-
203-
Concretely (for embedded Rust), that means `Send` and `Sync` can be used to
204-
model threads in an RTOS, or interrupt handlers for bare-metal applications.
205-
147+
(see above)
206148

207149
# Drawbacks
208150
[drawbacks]: #drawbacks
@@ -218,29 +160,27 @@ model threads in an RTOS, or interrupt handlers for bare-metal applications.
218160
expected that the actual cross-core communication is limited to a small number
219161
of places in the code, so making it more difficult has limited impact.
220162

221-
* `CoreSend` and `CoreSync` do not handle hypothetical cases in which
222-
peripherals or memory are shared between a *subset* of all cores. Examples of
223-
devices that have a configuration like this would be very welcome.
163+
* This RFC generally rules out SMP apps that run the same firmware image on
164+
multiple cores. These would be able to share data via `static`s, which only
165+
requires a `Sync` bound, and that is not sufficient to guarantee safe
166+
operation when accessed from multiple cores.
224167

225168
# Alternatives
226169
[alternatives]: #alternatives
227170

228171
* Accept [RFC 388] instead, introducing a `SingleCore{Send,Sync}` auto trait
229172
pair once auto traits are stable, and make `Mutex::new` an `unsafe fn` in the
230173
interim. Remove unsound `Send` impls from peripherals.
231-
* Do what this RFC proposes, but without the common `CoreSend`/`CoreSync`
232-
traits. Leave it to the ecosystem to find the right abstractions for
233-
multi-core MCUs.
234-
* Change the definition/contract of `CoreSync` to be "implements `Sync` and lies
235-
in and touches only memory accessible to all cores", which would mean that SMP
236-
apps could be supported while `bare_metal::Mutex` would still only be sound on
237-
single-core MCUs.
174+
175+
* Do what this RFC proposes, and also introduce `CoreSend`/`CoreSync` traits to
176+
model cross-core interaction. (This was what this RFC initially proposed, but
177+
it was decided that we should focus on fixing the soundness issues first and
178+
leave multi-core support to be implemented outside the core ecosystem.)
238179

239180
# Unresolved questions
240181
[unresolved]: #unresolved-questions
241182

242-
* Should `CoreSend` and `CoreSync` have `Send` and `Sync` as supertraits?
243-
* Should we provide `CoreSend` implementations for primitive types?
183+
* None so far.
244184

245185
[`bare_metal::Mutex`]: https://docs.rs/bare-metal/0.2.5/bare_metal/struct.Mutex.html
246186
[RFC 388]: https://github.com/rust-embedded/wg/pull/388

0 commit comments

Comments
 (0)