Fix if a enqueued instant is first in a non-empty queue

This commit is contained in:
Emil Fresk 2023-04-08 21:37:23 +02:00
parent d9f2980c38
commit 66780d8a7b
6 changed files with 20 additions and 17 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rtic-monotonics" name = "rtic-monotonics"
version = "1.0.0-alpha.0" version = "1.0.0-alpha.1"
edition = "2021" edition = "2021"
authors = [ authors = [
@ -17,7 +17,7 @@ license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
rtic-time = { version = "1.0.0-alpha.0", path = "../rtic-time" } rtic-time = { version = "1.0.0-alpha.1", path = "../rtic-time" }
embedded-hal-async = { version = "0.2.0-alpha.0", optional = true } embedded-hal-async = { version = "0.2.0-alpha.0", optional = true }
fugit = { version = "0.3.6" } fugit = { version = "0.3.6" }
atomic-polyfill = "1" atomic-polyfill = "1"

View file

@ -15,4 +15,6 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
### Fixed ### Fixed
- If the queue was non-empty and a new instant was added that was earlier than `head`, then the queue would no pend the monotonic handler. This would cause the new `head` to be dequeued at the wrong time.
## [v1.0.0] - 2023-xx-xx ## [v1.0.0] - 2023-xx-xx

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rtic-time" name = "rtic-time"
version = "1.0.0-alpha.0" version = "1.0.0-alpha.1"
edition = "2021" edition = "2021"
authors = [ authors = [

View file

@ -25,7 +25,7 @@ mod monotonic;
struct WaitingWaker<Mono: Monotonic> { struct WaitingWaker<Mono: Monotonic> {
waker: Waker, waker: Waker,
release_at: Mono::Instant, release_at: Mono::Instant,
was_poped: AtomicBool, was_popped: AtomicBool,
} }
impl<Mono: Monotonic> Clone for WaitingWaker<Mono> { impl<Mono: Monotonic> Clone for WaitingWaker<Mono> {
@ -33,7 +33,7 @@ impl<Mono: Monotonic> Clone for WaitingWaker<Mono> {
Self { Self {
waker: self.waker.clone(), waker: self.waker.clone(),
release_at: self.release_at, release_at: self.release_at,
was_poped: AtomicBool::new(self.was_poped.load(Ordering::Relaxed)), was_popped: AtomicBool::new(self.was_popped.load(Ordering::Relaxed)),
} }
} }
} }
@ -132,7 +132,7 @@ impl<Mono: Monotonic> TimerQueue<Mono> {
release_at = Some(head.release_at); release_at = Some(head.release_at);
let should_pop = Mono::should_dequeue_check(head.release_at); let should_pop = Mono::should_dequeue_check(head.release_at);
head.was_poped.store(should_pop, Ordering::Relaxed); head.was_popped.store(should_pop, Ordering::Relaxed);
should_pop should_pop
}); });
@ -234,7 +234,7 @@ impl<Mono: Monotonic> TimerQueue<Mono> {
let link_ref = link.insert(Link::new(WaitingWaker { let link_ref = link.insert(Link::new(WaitingWaker {
waker: cx.waker().clone(), waker: cx.waker().clone(),
release_at: instant, release_at: instant,
was_poped: AtomicBool::new(false), was_popped: AtomicBool::new(false),
})); }));
// SAFETY(new_unchecked): The address to the link is stable as it is defined // SAFETY(new_unchecked): The address to the link is stable as it is defined
@ -243,13 +243,13 @@ impl<Mono: Monotonic> TimerQueue<Mono> {
// we make sure in `dropper` that the link is removed from the queue before // we make sure in `dropper` that the link is removed from the queue before
// dropping `link_ptr` AND `dropper` makes sure that the shadowed `link_ptr` lives // dropping `link_ptr` AND `dropper` makes sure that the shadowed `link_ptr` lives
// until the end of the stack frame. // until the end of the stack frame.
let (was_empty, addr) = unsafe { queue.insert(Pin::new_unchecked(link_ref)) }; let (head_updated, addr) = unsafe { queue.insert(Pin::new_unchecked(link_ref)) };
marker.store(addr, Ordering::Relaxed); marker.store(addr, Ordering::Relaxed);
if was_empty { if head_updated {
// Pend the monotonic handler if the queue was empty to setup the timer. // Pend the monotonic handler if the queue head was updated.
Mono::pend_interrupt(); Mono::pend_interrupt()
} }
} }
@ -261,8 +261,8 @@ impl<Mono: Monotonic> TimerQueue<Mono> {
// exited the `poll_fn` below in the `drop(dropper)` call. The other dereference // exited the `poll_fn` below in the `drop(dropper)` call. The other dereference
// of this pointer is in the `poll_fn`. // of this pointer is in the `poll_fn`.
if let Some(link) = unsafe { link_ptr.get() } { if let Some(link) = unsafe { link_ptr.get() } {
if link.val.was_poped.load(Ordering::Relaxed) { if link.val.was_popped.load(Ordering::Relaxed) {
// If it was poped from the queue there is no need to run delete // If it was popped from the queue there is no need to run delete
dropper.defuse(); dropper.defuse();
} }
} else { } else {

View file

@ -92,7 +92,8 @@ impl<T: PartialOrd + Clone> LinkedList<T> {
} }
/// Insert a new link into the linked list. /// Insert a new link into the linked list.
/// The return is (was_empty, address), where the address of the link is for use with `delete`. /// The return is (updated head, address), where the address of the link is for use
/// with `delete`.
/// ///
/// SAFETY: The pinned link must live until it is removed from this list. /// SAFETY: The pinned link must live until it is removed from this list.
pub unsafe fn insert(&self, val: Pin<&Link<T>>) -> (bool, usize) { pub unsafe fn insert(&self, val: Pin<&Link<T>>) -> (bool, usize) {
@ -127,7 +128,7 @@ impl<T: PartialOrd + Clone> LinkedList<T> {
self.head self.head
.store(val as *const _ as *mut _, Ordering::Relaxed); .store(val as *const _ as *mut _, Ordering::Relaxed);
return (false, addr); return (true, addr);
} }
// 3. search list for correct place // 3. search list for correct place

View file

@ -22,7 +22,7 @@ name = "rtic"
readme = "../README.md" readme = "../README.md"
repository = "https://github.com/rtic-rs/rtic" repository = "https://github.com/rtic-rs/rtic"
version = "2.0.0-alpha.0" version = "2.0.0-alpha.1"
[lib] [lib]
name = "rtic" name = "rtic"
@ -32,7 +32,7 @@ cortex-m = { version = "0.7.0", optional = true }
bare-metal = "1.0.0" bare-metal = "1.0.0"
#portable-atomic = { version = "0.3.19" } #portable-atomic = { version = "0.3.19" }
atomic-polyfill = "1" atomic-polyfill = "1"
rtic-monotonics = { path = "../rtic-monotonics", version = "1.0.0-alpha.0", optional = true } rtic-monotonics = { path = "../rtic-monotonics", version = "1.0.0-alpha.1", optional = true }
rtic-macros = { path = "../rtic-macros", version = "2.0.0-alpha.0" } rtic-macros = { path = "../rtic-macros", version = "2.0.0-alpha.0" }
rtic-core = "1" rtic-core = "1"
critical-section = "1" critical-section = "1"