Fix UB
This commit is contained in:
parent
abf9a485c7
commit
f0c5fce17e
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#[cfg(not(single_queue))]
|
#[cfg(not(single_queue))]
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::cell::{RefCell, UnsafeCell};
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use embassy_sync::blocking_mutex::Mutex;
|
use embassy_sync::blocking_mutex::Mutex;
|
||||||
use esp_hal::{interrupt::Priority, sync::RawPriorityLimitedMutex};
|
use esp_hal::{interrupt::Priority, sync::RawPriorityLimitedMutex};
|
||||||
@ -14,12 +14,16 @@ use queue_impl::RawQueue;
|
|||||||
|
|
||||||
use crate::time_driver::{set_up_alarm, AlarmHandle};
|
use crate::time_driver::{set_up_alarm, AlarmHandle};
|
||||||
|
|
||||||
|
struct TimerQueueInner {
|
||||||
|
queue: RawQueue,
|
||||||
|
alarm: Option<AlarmHandle>,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct TimerQueue {
|
pub(crate) struct TimerQueue {
|
||||||
inner: Mutex<RawPriorityLimitedMutex, RefCell<RawQueue>>,
|
inner: Mutex<RawPriorityLimitedMutex, RefCell<TimerQueueInner>>,
|
||||||
priority: Priority,
|
priority: Priority,
|
||||||
#[cfg(not(single_queue))]
|
#[cfg(not(single_queue))]
|
||||||
context: Cell<*mut ()>,
|
context: Cell<*mut ()>,
|
||||||
alarm: UnsafeCell<Option<AlarmHandle>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for TimerQueue {}
|
unsafe impl Sync for TimerQueue {}
|
||||||
@ -29,12 +33,14 @@ impl TimerQueue {
|
|||||||
Self {
|
Self {
|
||||||
inner: Mutex::const_new(
|
inner: Mutex::const_new(
|
||||||
RawPriorityLimitedMutex::new(prio),
|
RawPriorityLimitedMutex::new(prio),
|
||||||
RefCell::new(RawQueue::new()),
|
RefCell::new(TimerQueueInner {
|
||||||
|
queue: RawQueue::new(),
|
||||||
|
alarm: None,
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
priority: prio,
|
priority: prio,
|
||||||
#[cfg(not(single_queue))]
|
#[cfg(not(single_queue))]
|
||||||
context: Cell::new(core::ptr::null_mut()),
|
context: Cell::new(core::ptr::null_mut()),
|
||||||
alarm: UnsafeCell::new(None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,33 +59,33 @@ impl TimerQueue {
|
|||||||
core::ptr::null_mut()
|
core::ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alarm(&self) -> AlarmHandle {
|
|
||||||
// FIXME this is UB on multi-core
|
|
||||||
unsafe {
|
|
||||||
let alarm = &mut *self.alarm.get();
|
|
||||||
*alarm.get_or_insert_with(|| set_up_alarm(self.priority, self.context()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dispatch(&self) {
|
pub fn dispatch(&self) {
|
||||||
let now = esp_hal::time::now().ticks();
|
let now = esp_hal::time::now().ticks();
|
||||||
let next_expiration = self.inner.lock(|q| q.borrow_mut().next_expiration(now));
|
self.arm_alarm(now);
|
||||||
self.arm_alarm(next_expiration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arm_alarm(&self, mut next_expiration: u64) {
|
fn arm_alarm(&self, mut next_expiration: u64) {
|
||||||
let alarm = self.alarm();
|
loop {
|
||||||
|
let set = self.inner.lock(|inner| {
|
||||||
|
let mut q = inner.borrow_mut();
|
||||||
|
next_expiration = q.queue.next_expiration(next_expiration);
|
||||||
|
|
||||||
while !alarm.update(next_expiration) {
|
let alarm = q
|
||||||
// next_expiration is in the past, dequeue and find a new expiration
|
.alarm
|
||||||
next_expiration = self
|
.get_or_insert_with(|| set_up_alarm(self.priority, self.context()));
|
||||||
.inner
|
alarm.update(next_expiration)
|
||||||
.lock(|q| q.borrow_mut().next_expiration(next_expiration));
|
});
|
||||||
|
if set {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
|
pub fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
|
||||||
if self.inner.lock(|q| q.borrow_mut().schedule_wake(at, waker)) {
|
if self
|
||||||
|
.inner
|
||||||
|
.lock(|inner| inner.borrow_mut().queue.schedule_wake(at, waker))
|
||||||
|
{
|
||||||
self.dispatch();
|
self.dispatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user