diff options
Diffstat (limited to 'embassy-executor/src/raw/run_queue.rs')
| -rw-r--r-- | embassy-executor/src/raw/run_queue.rs | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 9acb9dd28..97d26a18a 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs | |||
| @@ -157,19 +157,26 @@ fn run_dequeue(taskref: &TaskRef) { | |||
| 157 | /// A wrapper type that acts like TransferStack by wrapping a normal Stack in a CS mutex | 157 | /// A wrapper type that acts like TransferStack by wrapping a normal Stack in a CS mutex |
| 158 | #[cfg(not(target_has_atomic = "ptr"))] | 158 | #[cfg(not(target_has_atomic = "ptr"))] |
| 159 | struct MutexTransferStack<T: Linked<cordyceps::stack::Links<T>>> { | 159 | struct MutexTransferStack<T: Linked<cordyceps::stack::Links<T>>> { |
| 160 | inner: critical_section::Mutex<core::cell::RefCell<cordyceps::Stack<T>>>, | 160 | inner: critical_section::Mutex<core::cell::UnsafeCell<cordyceps::Stack<T>>>, |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | #[cfg(not(target_has_atomic = "ptr"))] | 163 | #[cfg(not(target_has_atomic = "ptr"))] |
| 164 | impl<T: Linked<cordyceps::stack::Links<T>>> MutexTransferStack<T> { | 164 | impl<T: Linked<cordyceps::stack::Links<T>>> MutexTransferStack<T> { |
| 165 | const fn new() -> Self { | 165 | const fn new() -> Self { |
| 166 | Self { | 166 | Self { |
| 167 | inner: critical_section::Mutex::new(core::cell::RefCell::new(cordyceps::Stack::new())), | 167 | inner: critical_section::Mutex::new(core::cell::UnsafeCell::new(cordyceps::Stack::new())), |
| 168 | } | 168 | } |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | /// Push an item to the transfer stack, returning whether the stack was previously empty | ||
| 171 | fn push_was_empty(&self, item: T::Handle, token: super::state::Token) -> bool { | 172 | fn push_was_empty(&self, item: T::Handle, token: super::state::Token) -> bool { |
| 172 | let mut guard = self.inner.borrow_ref_mut(token); | 173 | /// SAFETY: The critical-section mutex guarantees that there is no *concurrent* access |
| 174 | /// for the lifetime of the token, but does NOT protect against re-entrant access. | ||
| 175 | /// However, we never *return* the reference, nor do we recurse (or call another method | ||
| 176 | /// like `take_all`) that could ever allow for re-entrant aliasing. Therefore, the | ||
| 177 | /// presence of the critical section is sufficient to guarantee exclusive access to | ||
| 178 | /// the `inner` field for the purposes of this function | ||
| 179 | let mut guard = unsafe { &mut *self.inner.borrow(token).get() }; | ||
| 173 | let is_empty = guard.is_empty(); | 180 | let is_empty = guard.is_empty(); |
| 174 | guard.push(item); | 181 | guard.push(item); |
| 175 | is_empty | 182 | is_empty |
| @@ -177,7 +184,13 @@ impl<T: Linked<cordyceps::stack::Links<T>>> MutexTransferStack<T> { | |||
| 177 | 184 | ||
| 178 | fn take_all(&self) -> cordyceps::Stack<T> { | 185 | fn take_all(&self) -> cordyceps::Stack<T> { |
| 179 | critical_section::with(|cs| { | 186 | critical_section::with(|cs| { |
| 180 | let mut guard = self.inner.borrow_ref_mut(cs); | 187 | /// SAFETY: The critical-section mutex guarantees that there is no *concurrent* access |
| 188 | /// for the lifetime of the token, but does NOT protect against re-entrant access. | ||
| 189 | /// However, we never *return* the reference, nor do we recurse (or call another method | ||
| 190 | /// like `push_was_empty`) that could ever allow for re-entrant aliasing. Therefore, the | ||
| 191 | /// presence of the critical section is sufficient to guarantee exclusive access to | ||
| 192 | /// the `inner` field for the purposes of this function | ||
| 193 | let mut guard = unsafe { &mut *self.inner.borrow(cs).get() }; | ||
| 181 | guard.take_all() | 194 | guard.take_all() |
| 182 | }) | 195 | }) |
| 183 | } | 196 | } |
