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
@ -395,9 +395,8 @@ pub struct PortInputFuture<'a> {
|
|||||||
|
|
||||||
impl<'a> Drop for PortInputFuture<'a> {
|
impl<'a> Drop for PortInputFuture<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { AnyPin::steal(self.pin_port) }
|
let pin = unsafe { AnyPin::steal(self.pin_port) };
|
||||||
.conf()
|
pin.conf().modify(|_, w| w.sense().disabled());
|
||||||
.modify(|_, w| w.sense().disabled());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,18 +404,13 @@ impl<'a> Future for PortInputFuture<'a> {
|
|||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::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());
|
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::ptr::{self, NonNull};
|
||||||
use core::task::Waker;
|
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};
|
use crate::executor::raw::{task_from_waker, wake_task, TaskHeader};
|
||||||
|
|
||||||
@ -63,6 +63,7 @@ impl AtomicWaker {
|
|||||||
pub fn register(&self, w: &Waker) {
|
pub fn register(&self, w: &Waker) {
|
||||||
let w = unsafe { task_from_waker(w) };
|
let w = unsafe { task_from_waker(w) };
|
||||||
self.waker.store(w.as_ptr(), Ordering::Relaxed);
|
self.waker.store(w.as_ptr(), Ordering::Relaxed);
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wake the registered waker, if any.
|
/// Wake the registered waker, if any.
|
||||||
|
Loading…
Reference in New Issue
Block a user