aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/timer_queue.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src/raw/timer_queue.rs')
-rw-r--r--embassy-executor/src/raw/timer_queue.rs91
1 files changed, 27 insertions, 64 deletions
diff --git a/embassy-executor/src/raw/timer_queue.rs b/embassy-executor/src/raw/timer_queue.rs
index 94a5f340b..2ba0e00a9 100644
--- a/embassy-executor/src/raw/timer_queue.rs
+++ b/embassy-executor/src/raw/timer_queue.rs
@@ -1,76 +1,39 @@
1use core::cmp::min; 1//! Timer queue operations.
2
3use core::cell::Cell;
2 4
3use super::TaskRef; 5use super::TaskRef;
4use crate::raw::util::SyncUnsafeCell;
5 6
6pub(crate) struct TimerQueueItem { 7/// An item in the timer queue.
7 next: SyncUnsafeCell<Option<TaskRef>>, 8pub struct TimerQueueItem {
8} 9 /// The next item in the queue.
10 ///
11 /// If this field contains `Some`, the item is in the queue. The last item in the queue has a
12 /// value of `Some(dangling_pointer)`
13 pub next: Cell<Option<TaskRef>>,
9 14
10impl TimerQueueItem { 15 /// The time at which this item expires.
11 pub const fn new() -> Self { 16 pub expires_at: Cell<u64>,
12 Self {
13 next: SyncUnsafeCell::new(None),
14 }
15 }
16} 17}
17 18
18pub(crate) struct TimerQueue { 19unsafe impl Sync for TimerQueueItem {}
19 head: SyncUnsafeCell<Option<TaskRef>>,
20}
21 20
22impl TimerQueue { 21impl TimerQueueItem {
23 pub const fn new() -> Self { 22 pub(crate) const fn new() -> Self {
24 Self { 23 Self {
25 head: SyncUnsafeCell::new(None), 24 next: Cell::new(None),
26 } 25 expires_at: Cell::new(0),
27 }
28
29 pub(crate) unsafe fn update(&self, p: TaskRef) {
30 let task = p.header();
31 if task.expires_at.get() != u64::MAX {
32 if task.state.timer_enqueue() {
33 task.timer_queue_item.next.set(self.head.get());
34 self.head.set(Some(p));
35 }
36 } 26 }
37 } 27 }
28}
38 29
39 pub(crate) unsafe fn next_expiration(&self) -> u64 { 30/// The operation to perform after `timer_enqueue` is called.
40 let mut res = u64::MAX; 31#[derive(Debug, Copy, Clone, PartialEq)]
41 self.retain(|p| { 32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42 let task = p.header(); 33#[must_use]
43 let expires = task.expires_at.get(); 34pub enum TimerEnqueueOperation {
44 res = min(res, expires); 35 /// Enqueue the task (or update its expiration time).
45 expires != u64::MAX 36 Enqueue,
46 }); 37 /// The task must not be enqueued in the timer queue.
47 res 38 Ignore,
48 }
49
50 pub(crate) unsafe fn dequeue_expired(&self, now: u64, on_task: impl Fn(TaskRef)) {
51 self.retain(|p| {
52 let task = p.header();
53 if task.expires_at.get() <= now {
54 on_task(p);
55 false
56 } else {
57 true
58 }
59 });
60 }
61
62 pub(crate) unsafe fn retain(&self, mut f: impl FnMut(TaskRef) -> bool) {
63 let mut prev = &self.head;
64 while let Some(p) = prev.get() {
65 let task = p.header();
66 if f(p) {
67 // Skip to next
68 prev = &task.timer_queue_item.next;
69 } else {
70 // Remove it
71 prev.set(task.timer_queue_item.next.get());
72 task.state.timer_dequeue();
73 }
74 }
75 }
76} 39}