nrf/gpiote: fix irq race condition
The interrupt could fire between checking if sense=disabled and registering the waker, in which case the future would get stuck.
This commit is contained in:
parent
4ce46df160
commit
1c9f98e1b6
2 changed files with 10 additions and 15 deletions
|
@ -395,9 +395,8 @@ pub struct PortInputFuture<'a> {
|
|||
|
||||
impl<'a> Drop for PortInputFuture<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { AnyPin::steal(self.pin_port) }
|
||||
.conf()
|
||||
.modify(|_, w| w.sense().disabled());
|
||||
let pin = unsafe { AnyPin::steal(self.pin_port) };
|
||||
pin.conf().modify(|_, w| w.sense().disabled());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,18 +404,13 @@ impl<'a> Future for PortInputFuture<'a> {
|
|||
type Output = ();
|
||||
|
||||
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let dis = unsafe { AnyPin::steal(self.pin_port) }
|
||||
.conf()
|
||||
.read()
|
||||
.sense()
|
||||
.is_disabled();
|
||||
|
||||
if dis {
|
||||
return Poll::Ready(());
|
||||
}
|
||||
|
||||
PORT_WAKERS[self.pin_port as usize].register(cx.waker());
|
||||
|
||||
Poll::Pending
|
||||
let pin = unsafe { AnyPin::steal(self.pin_port) };
|
||||
if pin.conf().read().sense().is_disabled() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use core::ptr::{self, NonNull};
|
||||
use core::task::Waker;
|
||||
|
||||
use atomic_polyfill::{AtomicPtr, Ordering};
|
||||
use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering};
|
||||
|
||||
use crate::executor::raw::{task_from_waker, wake_task, TaskHeader};
|
||||
|
||||
|
@ -63,6 +63,7 @@ impl AtomicWaker {
|
|||
pub fn register(&self, w: &Waker) {
|
||||
let w = unsafe { task_from_waker(w) };
|
||||
self.waker.store(w.as_ptr(), Ordering::Relaxed);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// Wake the registered waker, if any.
|
||||
|
|
Loading…
Reference in a new issue