Skip to content

Commit 54a1aee

Browse files
committed
zephyr: embassy: executor: Fix race in thread suspention
Ensure the atomic is set before waking the other thread to prevent a race where the other thread is able to run through the queue, but not sleep before we have a chance to wake it. Signed-off-by: David Brown <[email protected]>
1 parent dd669d3 commit 54a1aee

File tree

1 file changed

+7
-7
lines changed

1 file changed

+7
-7
lines changed

zephyr/src/embassy/executor.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ impl Executor {
4444
// simulate this, we will use the 'pend' atomic to count
4545
inner.poll();
4646
if !self.pend.swap(false, Ordering::SeqCst) {
47-
// printkln!("_suspend");
4847
k_thread_suspend(k_current_get());
4948
}
5049
}
@@ -66,15 +65,16 @@ fn __pender(context: *mut ()) {
6665
let this = context as *const Executor;
6766
let other = (*this).id;
6867

68+
// The atomic is our equivalent to causing an event (wfe) or pending an IRQ. We need to do
69+
// this before waking the other thread in case that thread runs early. This is needed for
70+
// both the case of another thread, to prevent a race between the `inner.poll()` above, and
71+
// new items being added to the queue, as well as running entirely locally, also to prevent
72+
// the same race.
73+
(*this).pend.store(true, Ordering::SeqCst);
74+
6975
// If the other is a different thread, resume it.
7076
if other != myself {
71-
// printkln!("_resume");
7277
k_thread_resume(other);
7378
}
74-
// Otherwise, we need to make sure our own next suspend doesn't happen.
75-
// We need to also prevent a suspend from happening in the case where the only running
76-
// thread causes other work to become pending. The resume below will do nothing, as we
77-
// are just running.
78-
(*this).pend.store(true, Ordering::SeqCst);
7979
}
8080
}

0 commit comments

Comments
 (0)