capsules_core/virtualizers/
virtual_timer.rs1use core::cell::Cell;
8use core::cmp;
9
10use kernel::ErrorCode;
11use kernel::collections::list::{List, ListLink, ListNode};
12use kernel::hil::time::{self, Alarm, Ticks, Time, Timer};
13use kernel::utilities::cells::{NumericCellExt, OptionalCell};
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 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 }
60
61 pub fn setup(&'a self) {
64 self.mux.timers.push_head(self);
65 }
66
67 fn start_timer(&self, interval: A::Ticks, mode: Mode) -> A::Ticks {
69 if self.mode.get() == Mode::Disabled {
70 self.mux.enabled.increment();
71 }
72 self.mode.set(mode);
73
74 let real_interval: A::Ticks = A::Ticks::from(cmp::max(
76 interval.into_u32(),
77 self.mux.alarm.minimum_dt().into_u32(),
78 ));
79
80 let now = self.mux.alarm.now();
81 self.interval.set(real_interval);
82 self.when.set(now.wrapping_add(real_interval));
83 self.mux.calculate_alarm(now, real_interval);
84
85 real_interval
86 }
87}
88
89impl<'a, A: Alarm<'a>> Time for VirtualTimer<'a, A> {
90 type Frequency = A::Frequency;
91 type Ticks = A::Ticks;
92
93 fn now(&self) -> A::Ticks {
94 self.mux.alarm.now()
95 }
96}
97
98impl<'a, A: Alarm<'a>> Timer<'a> for VirtualTimer<'a, A> {
99 fn set_timer_client(&self, client: &'a dyn time::TimerClient) {
100 self.client.set(client);
101 }
102
103 fn cancel(&self) -> Result<(), ErrorCode> {
104 match self.mode.get() {
105 Mode::Disabled => Ok(()),
106 Mode::OneShot | Mode::Repeating => {
107 self.mode.set(Mode::Disabled);
108 self.mux.enabled.decrement();
109
110 if self.mux.enabled.get() == 0 {
113 let _ = self.mux.alarm.disarm();
114 }
115 Ok(())
116 }
117 }
118 }
119
120 fn interval(&self) -> Option<Self::Ticks> {
121 match self.mode.get() {
122 Mode::Disabled => None,
123 Mode::OneShot | Mode::Repeating => Some(self.interval.get()),
124 }
125 }
126
127 fn is_oneshot(&self) -> bool {
128 self.mode.get() == Mode::OneShot
129 }
130
131 fn is_repeating(&self) -> bool {
132 self.mode.get() == Mode::Repeating
133 }
134
135 fn is_enabled(&self) -> bool {
136 match self.mode.get() {
137 Mode::Disabled => false,
138 Mode::OneShot | Mode::Repeating => true,
139 }
140 }
141
142 fn oneshot(&self, interval: Self::Ticks) -> Self::Ticks {
143 self.start_timer(interval, Mode::OneShot)
144 }
145
146 fn repeating(&self, interval: Self::Ticks) -> Self::Ticks {
147 self.start_timer(interval, Mode::Repeating)
148 }
149
150 fn time_remaining(&self) -> Option<Self::Ticks> {
151 match self.mode.get() {
152 Mode::Disabled => None,
153 Mode::OneShot | Mode::Repeating => {
154 let when = self.when.get();
155 let now = self.mux.alarm.now();
156 Some(when.wrapping_sub(now))
157 }
158 }
159 }
160}
161
162impl<'a, A: Alarm<'a>> time::AlarmClient for VirtualTimer<'a, A> {
163 fn alarm(&self) {
164 match self.mode.get() {
165 Mode::Disabled => {} Mode::OneShot => {
167 self.mode.set(Mode::Disabled);
168 self.client.map(|client| client.timer());
169 }
170 Mode::Repeating => {
171 let when = self.when.get();
175 let interval = self.interval.get();
176 self.when.set(when.wrapping_add(interval));
177 self.mux.calculate_alarm(when, interval);
178 self.client.map(|client| client.timer());
179 }
180 }
181 }
182}
183
184pub struct MuxTimer<'a, A: Alarm<'a>> {
186 timers: List<'a, VirtualTimer<'a, A>>,
188 enabled: Cell<usize>,
190 alarm: &'a VirtualMuxAlarm<'a, A>,
192}
193
194impl<'a, A: Alarm<'a>> MuxTimer<'a, A> {
195 pub const fn new(alarm: &'a VirtualMuxAlarm<'a, A>) -> MuxTimer<'a, A> {
196 MuxTimer {
197 timers: List::new(),
198 enabled: Cell::new(0),
199 alarm,
200 }
201 }
202
203 fn calculate_alarm(&self, now: A::Ticks, interval: A::Ticks) {
204 if self.enabled.get() == 1 {
205 self.alarm.set_alarm(now, interval);
207 } else {
208 let cur_alarm = self.alarm.get_alarm();
214 let when = now.wrapping_add(interval);
215 if !cur_alarm.within_range(now, when) {
216 self.alarm.set_alarm(now, interval);
218 } else {
219 }
221 }
222 }
223}
224
225impl<'a, A: Alarm<'a>> time::AlarmClient for MuxTimer<'a, A> {
226 fn alarm(&self) {
227 let now = self.alarm.get_alarm();
231 self.timers
234 .iter()
235 .filter(|cur| {
236 cur.is_enabled()
237 && !now.within_range(
238 cur.when.get().wrapping_sub(cur.interval.get()),
239 cur.when.get(),
240 )
241 })
242 .for_each(|cur| {
243 cur.alarm();
244 });
245
246 let next = self
250 .timers
251 .iter()
252 .filter(|cur| cur.is_enabled())
253 .min_by_key(|cur| cur.when.get().wrapping_sub(now).into_u32());
254
255 if let Some(valrm) = next {
257 self.alarm
258 .set_alarm(now, valrm.when.get().wrapping_sub(now));
259 } else {
260 let _ = self.alarm.disarm();
261 }
262 }
263}