capsules_core/virtualizers/
virtual_timer.rs1use core::cell::Cell;
8use core::cmp;
9
10use kernel::collections::list::{List, ListLink, ListNode};
11use kernel::hil::time::{self, Alarm, Ticks, Time, Timer};
12use kernel::utilities::cells::{NumericCellExt, OptionalCell};
13use kernel::ErrorCode;
14
15use crate::virtualizers::virtual_alarm::VirtualMuxAlarm;
16
17#[derive(Copy, Clone, Debug, PartialEq)]
18enum Mode {
19 Disabled,
20 OneShot,
21 Repeating,
22}
23
24pub struct VirtualTimer<'a, A: Alarm<'a>> {
27 mux: &'a MuxTimer<'a, A>,
29 when: Cell<A::Ticks>,
31 interval: Cell<A::Ticks>,
33 mode: Cell<Mode>,
35 next: ListLink<'a, VirtualTimer<'a, A>>,
37 client: OptionalCell<&'a dyn time::TimerClient>,
39}
40
41impl<'a, A: Alarm<'a>> ListNode<'a, VirtualTimer<'a, A>> for VirtualTimer<'a, A> {
42 fn next(&self) -> &'a ListLink<VirtualTimer<'a, A>> {
43 &self.next
44 }
45}
46
47impl<'a, A: Alarm<'a>> VirtualTimer<'a, A> {
48 pub fn new(mux_timer: &'a MuxTimer<'a, A>) -> VirtualTimer<'a, A> {
50 let zero = A::Ticks::from(0);
51 let v = VirtualTimer {
52 mux: mux_timer,
53 when: Cell::new(zero),
54 interval: Cell::new(zero),
55 mode: Cell::new(Mode::Disabled),
56 next: ListLink::empty(),
57 client: OptionalCell::empty(),
58 };
59 v
60 }
61
62 pub fn setup(&'a self) {
65 self.mux.timers.push_head(self);
66 }
67
68 fn start_timer(&self, interval: A::Ticks, mode: Mode) -> A::Ticks {
70 if self.mode.get() == Mode::Disabled {
71 self.mux.enabled.increment();
72 }
73 self.mode.set(mode);
74
75 let real_interval: A::Ticks = A::Ticks::from(cmp::max(
77 interval.into_u32(),
78 self.mux.alarm.minimum_dt().into_u32(),
79 ));
80
81 let now = self.mux.alarm.now();
82 self.interval.set(real_interval);
83 self.when.set(now.wrapping_add(real_interval));
84 self.mux.calculate_alarm(now, real_interval);
85
86 real_interval
87 }
88}
89
90impl<'a, A: Alarm<'a>> Time for VirtualTimer<'a, A> {
91 type Frequency = A::Frequency;
92 type Ticks = A::Ticks;
93
94 fn now(&self) -> A::Ticks {
95 self.mux.alarm.now()
96 }
97}
98
99impl<'a, A: Alarm<'a>> Timer<'a> for VirtualTimer<'a, A> {
100 fn set_timer_client(&self, client: &'a dyn time::TimerClient) {
101 self.client.set(client);
102 }
103
104 fn cancel(&self) -> Result<(), ErrorCode> {
105 match self.mode.get() {
106 Mode::Disabled => Ok(()),
107 Mode::OneShot | Mode::Repeating => {
108 self.mode.set(Mode::Disabled);
109 self.mux.enabled.decrement();
110
111 if self.mux.enabled.get() == 0 {
114 let _ = self.mux.alarm.disarm();
115 }
116 Ok(())
117 }
118 }
119 }
120
121 fn interval(&self) -> Option<Self::Ticks> {
122 match self.mode.get() {
123 Mode::Disabled => None,
124 Mode::OneShot | Mode::Repeating => Some(self.interval.get()),
125 }
126 }
127
128 fn is_oneshot(&self) -> bool {
129 self.mode.get() == Mode::OneShot
130 }
131
132 fn is_repeating(&self) -> bool {
133 self.mode.get() == Mode::Repeating
134 }
135
136 fn is_enabled(&self) -> bool {
137 match self.mode.get() {
138 Mode::Disabled => false,
139 Mode::OneShot | Mode::Repeating => true,
140 }
141 }
142
143 fn oneshot(&self, interval: Self::Ticks) -> Self::Ticks {
144 self.start_timer(interval, Mode::OneShot)
145 }
146
147 fn repeating(&self, interval: Self::Ticks) -> Self::Ticks {
148 self.start_timer(interval, Mode::Repeating)
149 }
150
151 fn time_remaining(&self) -> Option<Self::Ticks> {
152 match self.mode.get() {
153 Mode::Disabled => None,
154 Mode::OneShot | Mode::Repeating => {
155 let when = self.when.get();
156 let now = self.mux.alarm.now();
157 Some(when.wrapping_sub(now))
158 }
159 }
160 }
161}
162
163impl<'a, A: Alarm<'a>> time::AlarmClient for VirtualTimer<'a, A> {
164 fn alarm(&self) {
165 match self.mode.get() {
166 Mode::Disabled => {} Mode::OneShot => {
168 self.mode.set(Mode::Disabled);
169 self.client.map(|client| client.timer());
170 }
171 Mode::Repeating => {
172 let when = self.when.get();
176 let interval = self.interval.get();
177 self.when.set(when.wrapping_add(interval));
178 self.mux.calculate_alarm(when, interval);
179 self.client.map(|client| client.timer());
180 }
181 }
182 }
183}
184
185pub struct MuxTimer<'a, A: Alarm<'a>> {
187 timers: List<'a, VirtualTimer<'a, A>>,
189 enabled: Cell<usize>,
191 alarm: &'a VirtualMuxAlarm<'a, A>,
193}
194
195impl<'a, A: Alarm<'a>> MuxTimer<'a, A> {
196 pub const fn new(alarm: &'a VirtualMuxAlarm<'a, A>) -> MuxTimer<'a, A> {
197 MuxTimer {
198 timers: List::new(),
199 enabled: Cell::new(0),
200 alarm,
201 }
202 }
203
204 fn calculate_alarm(&self, now: A::Ticks, interval: A::Ticks) {
205 if self.enabled.get() == 1 {
206 self.alarm.set_alarm(now, interval);
208 } else {
209 let cur_alarm = self.alarm.get_alarm();
215 let when = now.wrapping_add(interval);
216 if !cur_alarm.within_range(now, when) {
217 self.alarm.set_alarm(now, interval);
219 } else {
220 }
222 }
223 }
224}
225
226impl<'a, A: Alarm<'a>> time::AlarmClient for MuxTimer<'a, A> {
227 fn alarm(&self) {
228 let now = self.alarm.get_alarm();
232 self.timers
235 .iter()
236 .filter(|cur| {
237 cur.is_enabled()
238 && !now.within_range(
239 cur.when.get().wrapping_sub(cur.interval.get()),
240 cur.when.get(),
241 )
242 })
243 .for_each(|cur| {
244 cur.alarm();
245 });
246
247 let next = self
251 .timers
252 .iter()
253 .filter(|cur| cur.is_enabled())
254 .min_by_key(|cur| cur.when.get().wrapping_sub(now).into_u32());
255
256 if let Some(valrm) = next {
258 self.alarm
259 .set_alarm(now, valrm.when.get().wrapping_sub(now));
260 } else {
261 let _ = self.alarm.disarm();
262 }
263 }
264}