diff options
| author | Emil Fresk <emil.fresk@gmail.com> | 2023-01-23 20:57:56 +0100 |
|---|---|---|
| committer | Henrik Tjäder <henrik@tjaders.com> | 2023-03-01 00:33:31 +0100 |
| commit | 71b5f9438e1beb5fe12b90415d9d6307e79c0cdf (patch) | |
| tree | d355da4f316ef5162916d99aebe9aa3a47ca7909 /rtic-timer/src/linked_list.rs | |
| parent | 0f6ae7c1dd0ce10a83682a922bf68aca9121df1c (diff) | |
Fixed systick monotonic
Diffstat (limited to 'rtic-timer/src/linked_list.rs')
| -rw-r--r-- | rtic-timer/src/linked_list.rs | 173 |
1 files changed, 0 insertions, 173 deletions
diff --git a/rtic-timer/src/linked_list.rs b/rtic-timer/src/linked_list.rs deleted file mode 100644 index 42ff8cb..0000000 --- a/rtic-timer/src/linked_list.rs +++ /dev/null @@ -1,173 +0,0 @@ -//! ... - -use core::marker::PhantomPinned; -use core::sync::atomic::{AtomicPtr, Ordering}; -use critical_section as cs; - -/// A sorted linked list for the timer queue. -pub struct LinkedList<T> { - head: AtomicPtr<Link<T>>, -} - -impl<T> LinkedList<T> { - /// Create a new linked list. - pub const fn new() -> Self { - Self { - head: AtomicPtr::new(core::ptr::null_mut()), - } - } -} - -impl<T: PartialOrd + Clone> LinkedList<T> { - /// Pop the first element in the queue if the closure returns true. - pub fn pop_if<F: FnOnce(&T) -> bool>(&self, f: F) -> Option<T> { - cs::with(|_| { - // Make sure all previous writes are visible - core::sync::atomic::fence(Ordering::SeqCst); - - let head = self.head.load(Ordering::Relaxed); - - // SAFETY: `as_ref` is safe as `insert` requires a valid reference to a link - if let Some(head) = unsafe { head.as_ref() } { - if f(&head.val) { - // Move head to the next element - self.head - .store(head.next.load(Ordering::Relaxed), Ordering::Relaxed); - - // We read the value at head - let head_val = head.val.clone(); - - return Some(head_val); - } - } - None - }) - } - - /// Delete a link at an address. - pub fn delete(&self, addr: usize) { - cs::with(|_| { - // Make sure all previous writes are visible - core::sync::atomic::fence(Ordering::SeqCst); - - let head = self.head.load(Ordering::Relaxed); - - // SAFETY: `as_ref` is safe as `insert` requires a valid reference to a link - let head_ref = if let Some(head_ref) = unsafe { head.as_ref() } { - head_ref - } else { - // 1. List is empty, do nothing - return; - }; - - if head as *const _ as usize == addr { - // 2. Replace head with head.next - self.head - .store(head_ref.next.load(Ordering::Relaxed), Ordering::Relaxed); - - return; - } - - // 3. search list for correct node - let mut curr = head_ref; - let mut next = head_ref.next.load(Ordering::Relaxed); - - // SAFETY: `as_ref` is safe as `insert` requires a valid reference to a link - while let Some(next_link) = unsafe { next.as_ref() } { - // Next is not null - - if next as *const _ as usize == addr { - curr.next - .store(next_link.next.load(Ordering::Relaxed), Ordering::Relaxed); - - return; - } - - // Continue searching - curr = next_link; - next = next_link.next.load(Ordering::Relaxed); - } - }) - } - - /// 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`. - pub fn insert(&self, val: &mut Link<T>) -> (bool, usize) { - cs::with(|_| { - let addr = val as *const _ as usize; - - // Make sure all previous writes are visible - core::sync::atomic::fence(Ordering::SeqCst); - - let head = self.head.load(Ordering::Relaxed); - - // 3 cases to handle - - // 1. List is empty, write to head - // SAFETY: `as_ref` is safe as `insert` requires a valid reference to a link - let head_ref = if let Some(head_ref) = unsafe { head.as_ref() } { - head_ref - } else { - self.head.store(val, Ordering::Relaxed); - return (true, addr); - }; - - // 2. val needs to go in first - if val.val < head_ref.val { - // Set current head as next of `val` - val.next.store(head, Ordering::Relaxed); - - // `val` is now first in the queue - self.head.store(val, Ordering::Relaxed); - - return (false, addr); - } - - // 3. search list for correct place - let mut curr = head_ref; - let mut next = head_ref.next.load(Ordering::Relaxed); - - // SAFETY: `as_ref` is safe as `insert` requires a valid reference to a link - while let Some(next_link) = unsafe { next.as_ref() } { - // Next is not null - - if val.val < next_link.val { - // Replace next with `val` - val.next.store(next, Ordering::Relaxed); - - // Insert `val` - curr.next.store(val, Ordering::Relaxed); - - return (false, addr); - } - - // Continue searching - curr = next_link; - next = next_link.next.load(Ordering::Relaxed); - } - - // No next, write link to last position in list - curr.next.store(val, Ordering::Relaxed); - - (false, addr) - }) - } -} - -/// A link in the linked list. -pub struct Link<T> { - val: T, - next: AtomicPtr<Link<T>>, - _up: PhantomPinned, -} - -impl<T> Link<T> { - /// Create a new link. - pub const fn new(val: T) -> Self { - Self { - val, - next: AtomicPtr::new(core::ptr::null_mut()), - _up: PhantomPinned, - } - } -} |
