Merge #1459
1459: rp/multicore: fix undefined behavior in multicore spawn. r=Dirbaio a=Dirbaio It is UB to pass `entry` to core1 as `&mut`, because core0 keeps an aliasing pointer to that memory region, and actually writes to it (when `spawn_core1` returns, the stack frame gets deallocated and the memory gets reused). This violates noalias requirements. Added the fence just in case, een though it works without. bors r+ Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
commit
34a0c2172b
1 changed files with 8 additions and 3 deletions
|
@ -122,11 +122,16 @@ where
|
||||||
extern "C" fn core1_startup<F: FnOnce() -> bad::Never>(
|
extern "C" fn core1_startup<F: FnOnce() -> bad::Never>(
|
||||||
_: u64,
|
_: u64,
|
||||||
_: u64,
|
_: u64,
|
||||||
entry: &mut ManuallyDrop<F>,
|
entry: *mut ManuallyDrop<F>,
|
||||||
stack_bottom: *mut usize,
|
stack_bottom: *mut usize,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
core1_setup(stack_bottom);
|
core1_setup(stack_bottom);
|
||||||
let entry = unsafe { ManuallyDrop::take(entry) };
|
|
||||||
|
let entry = unsafe { ManuallyDrop::take(&mut *entry) };
|
||||||
|
|
||||||
|
// make sure the preceding read doesn't get reordered past the following fifo write
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
// Signal that it's safe for core 0 to get rid of the original value now.
|
// Signal that it's safe for core 0 to get rid of the original value now.
|
||||||
fifo_write(1);
|
fifo_write(1);
|
||||||
|
|
||||||
|
@ -164,7 +169,7 @@ where
|
||||||
|
|
||||||
// Push `entry`.
|
// Push `entry`.
|
||||||
stack_ptr = stack_ptr.sub(1);
|
stack_ptr = stack_ptr.sub(1);
|
||||||
stack_ptr.cast::<&mut ManuallyDrop<F>>().write(&mut entry);
|
stack_ptr.cast::<*mut ManuallyDrop<F>>().write(&mut entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the compiler does not reorder the stack writes after to after the
|
// Make sure the compiler does not reorder the stack writes after to after the
|
||||||
|
|
Loading…
Reference in a new issue