aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2024-12-08 23:21:53 +0100
committerDániel Buga <[email protected]>2024-12-12 15:38:52 +0100
commitd45ea43892198484b5f6dcea4c351dc11d226cc4 (patch)
tree54dd8011d3dea264095c28c8be003f66f8600ce6 /embassy-executor/src
parentdc18ee29a0f93ce34892731ee0580a3e9e3f2298 (diff)
Move integrated timer queue into time-queue-driver
Diffstat (limited to 'embassy-executor/src')
-rw-r--r--embassy-executor/src/raw/timer_queue.rs96
-rw-r--r--embassy-executor/src/raw/util.rs5
2 files changed, 11 insertions, 90 deletions
diff --git a/embassy-executor/src/raw/timer_queue.rs b/embassy-executor/src/raw/timer_queue.rs
index e0a22f4d4..46e346c1b 100644
--- a/embassy-executor/src/raw/timer_queue.rs
+++ b/embassy-executor/src/raw/timer_queue.rs
@@ -1,99 +1,25 @@
1//! Timer queue operations. 1//! Timer queue operations.
2use core::cmp::min;
3 2
4use super::util::SyncUnsafeCell; 3use core::cell::Cell;
4
5use super::TaskRef; 5use super::TaskRef;
6 6
7/// An item in the timer queue. 7/// An item in the timer queue.
8pub struct TimerQueueItem { 8pub struct TimerQueueItem {
9 next: SyncUnsafeCell<Option<TaskRef>>, 9 /// The next item in the queue.
10 expires_at: SyncUnsafeCell<u64>, 10 pub next: Cell<Option<TaskRef>>,
11}
12 11
13impl TimerQueueItem { 12 /// The time at which this item expires.
14 pub(crate) const fn new() -> Self { 13 pub expires_at: Cell<u64>,
15 Self {
16 next: SyncUnsafeCell::new(None),
17 expires_at: SyncUnsafeCell::new(0),
18 }
19 }
20} 14}
21 15
22/// A timer queue, with items integrated into tasks. 16unsafe impl Sync for TimerQueueItem {}
23pub struct TimerQueue {
24 head: SyncUnsafeCell<Option<TaskRef>>,
25}
26 17
27impl TimerQueue { 18impl TimerQueueItem {
28 /// Creates a new timer queue. 19 pub(crate) const fn new() -> Self {
29 pub const fn new() -> Self {
30 Self { 20 Self {
31 head: SyncUnsafeCell::new(None), 21 next: Cell::new(None),
32 } 22 expires_at: Cell::new(0),
33 }
34
35 /// Schedules a task to run at a specific time.
36 ///
37 /// If this function returns `true`, the called should find the next expiration time and set
38 /// a new alarm for that time.
39 pub fn schedule_wake(&mut self, at: u64, p: TaskRef) -> bool {
40 unsafe {
41 let item = p.timer_queue_item();
42 if item.next.get().is_none() {
43 // If not in the queue, add it and update.
44 let prev = self.head.replace(Some(p));
45 item.next.set(prev);
46 } else if at <= item.expires_at.get() {
47 // If expiration is sooner than previously set, update.
48 } else {
49 // Task does not need to be updated.
50 return false;
51 }
52
53 item.expires_at.set(at);
54 true
55 }
56 }
57
58 /// Dequeues expired timers and returns the next alarm time.
59 ///
60 /// The provided callback will be called for each expired task. Tasks that never expire
61 /// will be removed, but the callback will not be called.
62 pub fn next_expiration(&mut self, now: u64) -> u64 {
63 let mut next_expiration = u64::MAX;
64
65 self.retain(|p| {
66 let item = p.timer_queue_item();
67 let expires = unsafe { item.expires_at.get() };
68
69 if expires <= now {
70 // Timer expired, process task.
71 super::wake_task(p);
72 false
73 } else {
74 // Timer didn't yet expire, or never expires.
75 next_expiration = min(next_expiration, expires);
76 expires != u64::MAX
77 }
78 });
79
80 next_expiration
81 }
82
83 fn retain(&self, mut f: impl FnMut(TaskRef) -> bool) {
84 unsafe {
85 let mut prev = &self.head;
86 while let Some(p) = prev.get() {
87 let item = p.timer_queue_item();
88 if f(p) {
89 // Skip to next
90 prev = &item.next;
91 } else {
92 // Remove it
93 prev.set(item.next.get());
94 item.next.set(None);
95 }
96 }
97 } 23 }
98 } 24 }
99} 25}
diff --git a/embassy-executor/src/raw/util.rs b/embassy-executor/src/raw/util.rs
index e2633658a..c46085e45 100644
--- a/embassy-executor/src/raw/util.rs
+++ b/embassy-executor/src/raw/util.rs
@@ -54,9 +54,4 @@ impl<T> SyncUnsafeCell<T> {
54 { 54 {
55 *self.value.get() 55 *self.value.get()
56 } 56 }
57
58 #[cfg(feature = "integrated-timers")]
59 pub unsafe fn replace(&self, value: T) -> T {
60 core::mem::replace(&mut *self.value.get(), value)
61 }
62} 57}