diff options
author | 2022-10-08 20:40:45 +0200 | |
---|---|---|
committer | 2022-10-12 20:08:46 +0200 | |
commit | 613b3c59fc841caa3ca8c4d7ac440fbfa2f71fd1 (patch) | |
tree | 71fa6195eb7bf224716c23bb443249d4e8737727 | |
parent | 4ccc7d3dcb84f7f8e6556a4cd52efc18df1dc887 (diff) | |
download | rtic-613b3c59fc841caa3ca8c4d7ac440fbfa2f71fd1.tar.gz rtic-613b3c59fc841caa3ca8c4d7ac440fbfa2f71fd1.tar.zst rtic-613b3c59fc841caa3ca8c4d7ac440fbfa2f71fd1.zip |
Fixed a bug in the timer queue
When a waker was dequeued, and it had already exipired, the dequeue
was not re-run to set a proper new compare match for the monotonic.
This is now fixed.
-rw-r--r-- | src/tq.rs | 89 |
1 files changed, 49 insertions, 40 deletions
@@ -136,8 +136,7 @@ where instant: Mono::Instant, mono: &mut Mono, ) -> Option<(Task, u8)> { - let now = mono.now(); - if instant <= now { + if instant <= mono.now() { // task became ready let nr = unsafe { self.task_queue.pop_unchecked() }; Some((nr.task, nr.index)) @@ -149,7 +148,7 @@ where // dequeue. If the monotonic is fast enough it can happen that from the // read of now to the set of the compare, the time can overflow. This is to // guard against this. - if instant <= now { + if instant <= mono.now() { let nr = unsafe { self.task_queue.pop_unchecked() }; Some((nr.task, nr.index)) } else { @@ -158,12 +157,15 @@ where } } - fn dequeue_waker_queue(&mut self, instant: Mono::Instant, mono: &mut Mono) { - let now = mono.now(); - if instant <= now { + fn dequeue_waker_queue(&mut self, instant: Mono::Instant, mono: &mut Mono) -> bool { + let mut did_wake = false; + + if instant <= mono.now() { // Task became ready, wake the waker if let Some(v) = self.waker_queue.pop() { - v.val.waker.wake_by_ref() + v.val.waker.wake_by_ref(); + + did_wake = true; } } else { // Set compare @@ -173,12 +175,16 @@ where // dequeue. If the monotonic is fast enough it can happen that from the // read of now to the set of the compare, the time can overflow. This is to // guard against this. - if instant <= now { + if instant <= mono.now() { if let Some(v) = self.waker_queue.pop() { - v.val.waker.wake_by_ref() + v.val.waker.wake_by_ref(); + + did_wake = true; } } } + + did_wake } /// Dequeue a task from the ``TimerQueue`` @@ -188,47 +194,50 @@ where { mono.clear_compare_flag(); - let tq = self.task_queue.peek().map(|p| p.instant); - let wq = self.waker_queue.peek().map(|p| p.instant); - - let dequeue_task; - let instant; - - match (tq, wq) { - (Some(tq_instant), Some(wq_instant)) => { - if tq_instant <= wq_instant { + loop { + let tq = self.task_queue.peek().map(|p| p.instant); + let wq = self.waker_queue.peek().map(|p| p.instant); + + let dequeue_task; + let instant; + + match (tq, wq) { + (Some(tq_instant), Some(wq_instant)) => { + if tq_instant <= wq_instant { + dequeue_task = true; + instant = tq_instant; + } else { + dequeue_task = false; + instant = wq_instant; + } + } + (Some(tq_instant), None) => { dequeue_task = true; instant = tq_instant; - } else { + } + (None, Some(wq_instant)) => { dequeue_task = false; instant = wq_instant; } - } - (Some(tq_instant), None) => { - dequeue_task = true; - instant = tq_instant; - } - (None, Some(wq_instant)) => { - dequeue_task = false; - instant = wq_instant; - } - (None, None) => { - // The queue is empty, disable the interrupt. - if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE { - disable_interrupt(); - mono.disable_timer(); + (None, None) => { + // The queue is empty, disable the interrupt. + if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE { + disable_interrupt(); + mono.disable_timer(); + } + + return None; } + } + if dequeue_task { + return self.dequeue_task_queue(instant, mono); + } else if !self.dequeue_waker_queue(instant, mono) { return None; + } else { + // Run the dequeue again } } - - if dequeue_task { - self.dequeue_task_queue(instant, mono) - } else { - self.dequeue_waker_queue(instant, mono); - None - } } } |