aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/timer_queue.rs
diff options
context:
space:
mode:
authorjrmoulton <[email protected]>2025-06-10 15:47:54 -0600
committerjrmoulton <[email protected]>2025-06-10 15:48:36 -0600
commitcfad9798ff99d4de0571a512d156b5fe1ef1d427 (patch)
treefc3bf670f82d139de19466cddad1e909db7f3d2e /embassy-executor/src/raw/timer_queue.rs
parentfc342915e6155dec7bafa3e135da7f37a9a07f5c (diff)
parent6186d111a5c150946ee5b7e9e68d987a38c1a463 (diff)
merge new embassy changes
Diffstat (limited to 'embassy-executor/src/raw/timer_queue.rs')
-rw-r--r--embassy-executor/src/raw/timer_queue.rs119
1 files changed, 58 insertions, 61 deletions
diff --git a/embassy-executor/src/raw/timer_queue.rs b/embassy-executor/src/raw/timer_queue.rs
index 94a5f340b..e52453be4 100644
--- a/embassy-executor/src/raw/timer_queue.rs
+++ b/embassy-executor/src/raw/timer_queue.rs
@@ -1,76 +1,73 @@
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#[cfg(feature = "_timer-item-payload")]
7 next: SyncUnsafeCell<Option<TaskRef>>, 8macro_rules! define_opaque {
8} 9 ($size:tt) => {
10 /// An opaque data type.
11 #[repr(align($size))]
12 pub struct OpaqueData {
13 data: [u8; $size],
14 }
9 15
10impl TimerQueueItem { 16 impl OpaqueData {
11 pub const fn new() -> Self { 17 const fn new() -> Self {
12 Self { 18 Self { data: [0; $size] }
13 next: SyncUnsafeCell::new(None), 19 }
20
21 /// Access the data as a reference to a type `T`.
22 ///
23 /// Safety:
24 ///
25 /// The caller must ensure that the size of the type `T` is less than, or equal to
26 /// the size of the payload, and must ensure that the alignment of the type `T` is
27 /// less than, or equal to the alignment of the payload.
28 ///
29 /// The type must be valid when zero-initialized.
30 pub unsafe fn as_ref<T>(&self) -> &T {
31 &*(self.data.as_ptr() as *const T)
32 }
14 } 33 }
15 } 34 };
16} 35}
17 36
18pub(crate) struct TimerQueue { 37#[cfg(feature = "timer-item-payload-size-1")]
19 head: SyncUnsafeCell<Option<TaskRef>>, 38define_opaque!(1);
20} 39#[cfg(feature = "timer-item-payload-size-2")]
40define_opaque!(2);
41#[cfg(feature = "timer-item-payload-size-4")]
42define_opaque!(4);
43#[cfg(feature = "timer-item-payload-size-8")]
44define_opaque!(8);
21 45
22impl TimerQueue { 46/// An item in the timer queue.
23 pub const fn new() -> Self { 47pub struct TimerQueueItem {
24 Self { 48 /// The next item in the queue.
25 head: SyncUnsafeCell::new(None), 49 ///
26 } 50 /// If this field contains `Some`, the item is in the queue. The last item in the queue has a
27 } 51 /// value of `Some(dangling_pointer)`
52 pub next: Cell<Option<TaskRef>>,
28 53
29 pub(crate) unsafe fn update(&self, p: TaskRef) { 54 /// The time at which this item expires.
30 let task = p.header(); 55 pub expires_at: Cell<u64>,
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 }
37 }
38 56
39 pub(crate) unsafe fn next_expiration(&self) -> u64 { 57 /// Some implementation-defined, zero-initialized piece of data.
40 let mut res = u64::MAX; 58 #[cfg(feature = "_timer-item-payload")]
41 self.retain(|p| { 59 pub payload: OpaqueData,
42 let task = p.header(); 60}
43 let expires = task.expires_at.get();
44 res = min(res, expires);
45 expires != u64::MAX
46 });
47 res
48 }
49 61
50 pub(crate) unsafe fn dequeue_expired(&self, now: u64, on_task: impl Fn(TaskRef)) { 62unsafe impl Sync for TimerQueueItem {}
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 63
62 pub(crate) unsafe fn retain(&self, mut f: impl FnMut(TaskRef) -> bool) { 64impl TimerQueueItem {
63 let mut prev = &self.head; 65 pub(crate) const fn new() -> Self {
64 while let Some(p) = prev.get() { 66 Self {
65 let task = p.header(); 67 next: Cell::new(None),
66 if f(p) { 68 expires_at: Cell::new(0),
67 // Skip to next 69 #[cfg(feature = "_timer-item-payload")]
68 prev = &task.timer_queue_item.next; 70 payload: OpaqueData::new(),
69 } else {
70 // Remove it
71 prev.set(task.timer_queue_item.next.get());
72 task.state.timer_dequeue();
73 }
74 } 71 }
75 } 72 }
76} 73}