hermit/scheduler/
timer_interrupts.rs1use core::mem;
2
3use crate::core_local::core_scheduler;
4#[cfg(feature = "net")]
5use crate::executor::network::wake_network_waker;
6use crate::set_oneshot_timer;
7
8#[derive(Debug, PartialEq, Eq)]
11pub enum Source {
12 Network,
13 Scheduler,
14}
15
16#[derive(Debug)]
19pub struct Slot {
20 source: Source,
22 wakeup_time: u64,
26}
27
28#[derive(Debug)]
30pub struct TimerList([Slot; 2]);
31
32impl TimerList {
33 pub fn new() -> Self {
34 Self([
35 Slot {
36 source: Source::Network,
37 wakeup_time: u64::MAX,
38 },
39 Slot {
40 source: Source::Scheduler,
41 wakeup_time: u64::MAX,
42 },
43 ])
44 }
45
46 pub fn slot_by_source_mut(&mut self, source: Source) -> &mut Slot {
48 self.0
50 .iter_mut()
51 .find(|slot| slot.source == source)
52 .unwrap()
53 }
54
55 pub fn next_timer(&self) -> &Slot {
57 self.0
59 .iter()
60 .min_by(|a, b| a.wakeup_time.cmp(&b.wakeup_time))
61 .unwrap()
62 }
63
64 pub fn next_timer_mut(&mut self) -> &mut Slot {
66 self.0
68 .iter_mut()
69 .min_by(|a, b| a.wakeup_time.cmp(&b.wakeup_time))
70 .unwrap()
71 }
72
73 pub fn adjust_by(&mut self, offset: u64) {
75 for timer in self.0.iter_mut() {
76 if timer.wakeup_time != u64::MAX {
77 timer.wakeup_time -= offset;
78 }
79 }
80 }
81}
82
83impl Default for TimerList {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89#[cfg(feature = "net")]
91#[inline]
92pub fn create_timer(source: Source, wakeup_micros: u64) {
93 create_timer_abs(
94 source,
95 crate::arch::processor::get_timer_ticks() + wakeup_micros,
97 );
98}
99
100pub fn create_timer_abs(source: Source, wakeup_time: u64) {
102 let timers = &mut core_scheduler().timers;
103
104 let previous_entry = timers.slot_by_source_mut(source);
106
107 previous_entry.wakeup_time = previous_entry.wakeup_time.min(wakeup_time);
109
110 if timers.next_timer().wakeup_time == wakeup_time {
112 set_oneshot_timer(Some(wakeup_time));
113 }
114}
115
116pub fn clear_active_and_set_next() {
118 let timers = &mut core_scheduler().timers;
119
120 let lowest_timer = timers.next_timer_mut();
121 assert!(lowest_timer.wakeup_time != u64::MAX);
122
123 match lowest_timer.source {
125 #[cfg(feature = "net")]
126 Source::Network => wake_network_waker(),
127 _ => {} }
129
130 trace!("Cleared active timer {lowest_timer:?}");
131
132 let prev_wakeup_time = mem::replace(&mut lowest_timer.wakeup_time, u64::MAX);
133
134 let timer_ticks = crate::arch::processor::get_timer_ticks();
141 if prev_wakeup_time > timer_ticks {
142 let offset = prev_wakeup_time - timer_ticks;
143 timers.adjust_by(offset);
144 }
145
146 let new_lowest_timer = timers.next_timer().wakeup_time;
147
148 if new_lowest_timer == u64::MAX {
149 set_oneshot_timer(None);
150 } else {
151 set_oneshot_timer(Some(new_lowest_timer));
152 }
153}