@@ -12,12 +12,11 @@ Change how we model multi-core MCUs in the following ways:
12
12
interactions since those traits are unfit for the purpose.
13
13
* Declare that ` Send ` is not sufficient to transfer resources between cores,
14
14
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.
18
15
* Mutexes based on critical sections become declared sound due to the above:
19
16
They can only turn ` Send ` data ` Sync ` , but neither allows cross-core
20
17
interactions anymore.
18
+ * Punt on how to deal with cross-core communication and data sharing for now,
19
+ and leave it to the ecosystem.
21
20
22
21
# Motivation
23
22
[ motivation ] : #motivation
@@ -102,59 +101,20 @@ risk of the resources changing their meaning when sent.
102
101
# Detailed design
103
102
[ design ] : #detailed-design
104
103
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
146
105
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.
151
109
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.
153
115
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.
158
118
159
119
## ` bare_metal::Mutex ` is now sound
160
120
@@ -175,34 +135,16 @@ In SMP apps, only a single executable is used for all cores, while each core can
175
135
have a separate entry point (or another mechanism of identifying the running
176
136
core). This means that all ` static ` s are shared by default.
177
137
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.
184
143
185
144
# How We Teach This
186
145
[ how-we-teach-this ] : #how-we-teach-this
187
146
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)
206
148
207
149
# Drawbacks
208
150
[ drawbacks ] : #drawbacks
@@ -218,29 +160,27 @@ model threads in an RTOS, or interrupt handlers for bare-metal applications.
218
160
expected that the actual cross-core communication is limited to a small number
219
161
of places in the code, so making it more difficult has limited impact.
220
162
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.
224
167
225
168
# Alternatives
226
169
[ alternatives ] : #alternatives
227
170
228
171
* Accept [ RFC 388] instead, introducing a ` SingleCore{Send,Sync} ` auto trait
229
172
pair once auto traits are stable, and make ` Mutex::new ` an ` unsafe fn ` in the
230
173
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.)
238
179
239
180
# Unresolved questions
240
181
[ unresolved ] : #unresolved-questions
241
182
242
- * Should ` CoreSend ` and ` CoreSync ` have ` Send ` and ` Sync ` as supertraits?
243
- * Should we provide ` CoreSend ` implementations for primitive types?
183
+ * None so far.
244
184
245
185
[ `bare_metal::Mutex` ] : https://docs.rs/bare-metal/0.2.5/bare_metal/struct.Mutex.html
246
186
[ RFC 388 ] : https://github.com/rust-embedded/wg/pull/388
0 commit comments