1use crate::power::{
6 OnWakeOps, OwnedMessageCounterHandle, SharedMessageCounter,
7 create_proxy_for_wake_events_counter_zero,
8};
9use crate::task::dynamic_thread_spawner::SpawnRequestBuilder;
10use crate::task::{CurrentTask, Kernel, LockedAndTask};
11use crate::time::TargetTime;
12use crate::vfs::timer::{TimelineChangeObserver, TimerOps};
13use anyhow::{Context, Result};
14use fidl_fuchsia_time_alarms as fta;
15use fuchsia_async as fasync;
16use fuchsia_inspect::ArrayProperty;
17use fuchsia_runtime::UtcClock;
18use fuchsia_trace as ftrace;
19use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
20use futures::{FutureExt, SinkExt, StreamExt, select};
21use scopeguard::defer;
22use starnix_logging::{log_debug, log_error, log_info, log_warn};
23use starnix_sync::{HrTimerIsIntervalLock, HrTimerManagerStateLock, LockDepGuard, LockDepMutex};
24use starnix_uapi::errors::Errno;
25use starnix_uapi::{errno, from_status_like_fdio};
26use std::collections::{HashMap, VecDeque};
27use std::pin::pin;
28use std::sync::{Arc, OnceLock, Weak};
29use zx::HandleRef;
30
31const INSPECT_EVENT_BUFFER_SIZE: usize = 128;
33
34fn to_errno_with_log<T: std::fmt::Debug>(v: T) -> Errno {
35 log_error!("hr_timer_manager internal error: {v:?}");
36 from_status_like_fdio!(zx::Status::IO)
37}
38
39fn signal_event(
40 event: &zx::Event,
41 clear_mask: zx::Signals,
42 set_mask: zx::Signals,
43) -> Result<(), zx::Status> {
44 event
45 .signal(clear_mask, set_mask)
46 .inspect_err(|err| log_error!(err:?, clear_mask:?, set_mask:?; "while signaling event"))
47}
48
49const TIMEOUT_SECONDS: i64 = 40;
50fn wait_signaled_sync(event: &zx::Event) -> zx::WaitResult {
55 let mut logged = false;
56 loop {
57 let timeout =
58 zx::MonotonicInstant::after(zx::MonotonicDuration::from_seconds(TIMEOUT_SECONDS));
59 let result = event.wait_one(zx::Signals::EVENT_SIGNALED, timeout);
60 if let zx::WaitResult::Ok(_) = result {
61 if logged {
62 log_error!("wait_signaled_sync: signal resolved: result={result:?}",);
63 }
64 return result;
65 }
66 fuchsia_trace::instant!(
67 "alarms",
68 "starnix:hrtimer:wait_timeout",
69 fuchsia_trace::Scope::Process
70 );
71 log_error!(
74 "wait_signaled_sync: not signaled yet. Report to `componentid:1408151`: result={result:?}",
77 );
79 if !logged {
80 #[cfg(all(target_os = "fuchsia", not(doc)))]
81 ::debug::backtrace_request_all_threads();
82 logged = true;
83 }
84 }
85}
86
87macro_rules! log_long_op {
90 ($fut:expr) => {{
91 use futures::FutureExt;
92 let fut = $fut;
93 futures::pin_mut!(fut);
94 let mut logged = false;
95 loop {
96 let timeout = fasync::Timer::new(zx::MonotonicDuration::from_seconds(TIMEOUT_SECONDS));
97 futures::select! {
98 res = fut.as_mut().fuse() => {
99 if logged {
100 log_warn!("unexpected blocking is now resolved: long-running async operation at {}:{}.",
101 file!(), line!());
102 }
103 break res;
104 }
105 _ = timeout.fuse() => {
106 log_warn!("unexpected blocking: long-running async op at {}:{}. Report to `componentId:1408151`",
108 file!(), line!());
109 if !logged {
110 #[cfg(all(target_os = "fuchsia", not(doc)))]
111 ::debug::backtrace_request_all_threads();
112 }
113 logged = true;
114 }
115 }
116 }
117 }};
118}
119
120async fn wait_signaled<H: zx::AsHandleRef>(handle: &H) -> Result<()> {
122 log_long_op!(fasync::OnSignals::new(handle, zx::Signals::EVENT_SIGNALED))
123 .context("hr_timer_manager:wait_signaled")?;
124 Ok(())
125}
126
127async fn cancel_by_id(
129 _message_counter: &SharedMessageCounter,
130 timer_state: Option<TimerState>,
131 timer_id: &zx::Koid,
132 proxy: &fta::WakeAlarmsProxy,
133 interval_timers_pending_reschedule: &mut HashMap<zx::Koid, SharedMessageCounter>,
134 task_by_timer_id: &mut HashMap<zx::Koid, fasync::Task<()>>,
135 alarm_id: &str,
136) {
137 if let Some(task) = task_by_timer_id.remove(timer_id) {
138 task.detach();
140 }
141 if let Some(timer_state) = timer_state {
142 ftrace::duration!("alarms", "starnix:hrtimer:cancel_by_id", "timer_id" => *timer_id);
143 log_debug!("cancel_by_id: START canceling timer: {:?}: alarm_id: {}", timer_id, alarm_id);
144 proxy.cancel(&alarm_id).expect("infallible");
145 log_debug!("cancel_by_id: 1/2 canceling timer: {:?}: alarm_id: {}", timer_id, alarm_id);
146
147 let _ = log_long_op!(timer_state.task);
149 }
150
151 interval_timers_pending_reschedule.remove(timer_id);
155 log_debug!("cancel_by_id: 2/2 DONE canceling timer: {timer_id:?}: alarm_id: {alarm_id}");
156}
157
158fn process_alarm_protocol_error(
161 pending: &mut HashMap<zx::Koid, TimerState>,
162 timer_id: &zx::Koid,
163 error: fta::WakeAlarmsError,
164) -> Option<TimerState> {
165 match error {
166 fta::WakeAlarmsError::Unspecified => {
167 log_warn!(
168 "watch_new_hrtimer_loop: Cmd::AlarmProtocolFail: unspecified error: {error:?}"
169 );
170 pending.remove(timer_id)
171 }
172 fta::WakeAlarmsError::Dropped => {
173 log_debug!("watch_new_hrtimer_loop: Cmd::AlarmProtocolFail: alarm dropped: {error:?}");
174 None
178 }
179 error => {
180 log_warn!(
181 "watch_new_hrtimer_loop: Cmd::AlarmProtocolFail: unspecified error: {error:?}"
182 );
183 pending.remove(timer_id)
184 }
185 }
186}
187
188fn connect_to_wake_alarms_async() -> Result<zx::Channel, Errno> {
190 log_debug!("connecting to wake alarms");
191 let (client, server) = zx::Channel::create();
192 fuchsia_component::client::connect_channel_to_protocol::<fta::WakeAlarmsMarker>(server)
193 .map(|()| client)
194 .map_err(|err| {
195 errno!(EINVAL, format!("Failed to connect to fuchsia.time.alarms/Wake: {err}"))
196 })
197}
198
199#[derive(Debug)]
200enum InspectHrTimerEvent {
201 Add(#[allow(dead_code)] zx::Koid),
204 Update(#[allow(dead_code)] zx::Koid),
205 Remove(#[allow(dead_code)] zx::Koid),
206 Alarm(#[allow(dead_code)] zx::Koid),
208 Error(#[allow(dead_code)] String),
209}
210
211impl InspectHrTimerEvent {
212 fn retain_err(prev_len: usize, after_len: usize, context: &str) -> InspectHrTimerEvent {
213 InspectHrTimerEvent::Error(format!(
214 "retain the timer incorrectly, before len: {prev_len}, after len: {after_len}, context: {context}",
215 ))
216 }
217}
218
219impl std::fmt::Display for InspectHrTimerEvent {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 write!(f, "{:?}", self)
222 }
223}
224
225#[derive(Debug)]
226struct InspectEvent {
227 event_type: InspectHrTimerEvent,
228 created_at: zx::BootInstant,
229 deadline: Option<TargetTime>,
230}
231
232impl InspectEvent {
233 fn new(event_type: InspectHrTimerEvent, deadline: Option<TargetTime>) -> Self {
234 Self { event_type, created_at: zx::BootInstant::get(), deadline }
235 }
236}
237
238#[derive(Debug)]
239struct TimerState {
240 task: fasync::Task<()>,
242 deadline: TargetTime,
244 node: HrTimerNodeHandle,
246}
247
248impl std::fmt::Display for TimerState {
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 write!(f, "TimerState[deadline:{:?}]", self.deadline)
251 }
252}
253
254struct HrTimerManagerState {
255 pending_timers: HashMap<zx::Koid, TimerState>,
257
258 message_counter: Option<OwnedMessageCounterHandle>,
261
262 events: VecDeque<InspectEvent>,
264
265 last_loop_started_timestamp: zx::BootInstant,
267
268 last_loop_completed_timestamp: zx::BootInstant,
270
271 debug_start_stage_counter: u64,
274}
275
276impl HrTimerManagerState {
277 fn new(_parent_node: &fuchsia_inspect::Node) -> Self {
278 Self {
279 pending_timers: HashMap::new(),
280 message_counter: None,
283 events: VecDeque::with_capacity(INSPECT_EVENT_BUFFER_SIZE),
284 last_loop_started_timestamp: zx::BootInstant::INFINITE_PAST,
285 last_loop_completed_timestamp: zx::BootInstant::INFINITE_PAST,
286 debug_start_stage_counter: 0,
287 }
288 }
289
290 fn get_pending_timers_count(&self) -> usize {
291 self.pending_timers.len()
292 }
293
294 fn share_message_counter(&self, new_pending_message: bool) -> SharedMessageCounter {
296 let counter_ref =
297 self.message_counter.as_ref().expect("message_counter is None, but should not be.");
298 counter_ref.share(new_pending_message)
299 }
300
301 fn record_events(&self, node: &fuchsia_inspect::Node) {
302 let events_node = node.create_child("events");
303 for (i, event) in self.events.iter().enumerate() {
304 let child = events_node.create_child(i.to_string());
305 child.record_string("type", event.event_type.to_string());
306 child.record_int("created_at", event.created_at.into_nanos());
307 if let Some(deadline) = event.deadline {
308 child.record_int("deadline", deadline.estimate_boot().unwrap().into_nanos());
309 }
310 events_node.record(child);
311 }
312 node.record(events_node);
313 }
314}
315
316#[derive(Debug)]
324enum Cmd {
325 Start {
329 new_timer_node: HrTimerNodeHandle,
330 done: zx::Event,
332 message_counter: SharedMessageCounter,
335 },
336 Stop {
338 timer: HrTimerHandle,
340 done: zx::Event,
342 message_counter: SharedMessageCounter,
345 },
346 Alarm {
348 new_timer_node: HrTimerNodeHandle,
350 lease: zx::EventPair,
352 message_counter: SharedMessageCounter,
355 },
356 MonitorUtc { timer: HrTimerHandle, counter: zx::Counter, recv: mpsc::UnboundedReceiver<bool> },
358}
359
360async fn run_utc_timeline_monitor(counter: zx::Counter, recv: mpsc::UnboundedReceiver<bool>) {
378 let utc_handle = crate::time::utc::duplicate_real_utc_clock_handle().inspect_err(|err| {
379 log_error!("run_utc_timeline_monitor: could not monitor UTC timeline: {err:?}")
380 });
381 if let Ok(utc_handle) = utc_handle {
382 run_utc_timeline_monitor_internal(counter, recv, utc_handle).await;
383 }
384}
385
386async fn run_utc_timeline_monitor_internal(
389 counter: zx::Counter,
390 mut recv: mpsc::UnboundedReceiver<bool>,
391 utc_handle: UtcClock,
392) {
393 log_debug!("run_utc_timeline_monitor: monitoring UTC clock timeline changes: enter");
394 let koid = utc_handle.koid();
395 log_debug!(
396 "run_utc_timeline_monitor: monitoring UTC clock timeline: enter: UTC clock koid={koid:?}, counter={counter:?}"
397 );
398 let utc_handle = std::rc::Rc::new(utc_handle);
399 let utc_handle_fn = || utc_handle.clone();
400 let mut interested = false;
401 loop {
402 let utc_handle = utc_handle_fn();
403 let mut updated_fut = pin!(
405 fasync::OnSignals::new(utc_handle.as_handle_ref(), zx::Signals::CLOCK_UPDATED).fuse()
406 );
407 let mut interest_fut = recv.next();
408
409 select! {
412 result = updated_fut => {
413 if result.is_err() {
414 log_warn!("run_utc_timeline_monitor: could not wait on signals: {:?}, counter={counter:?}", result);
415 break;
416 }
417 if interested {
418 log_debug!("run_utc_timeline_monitor: UTC timeline updated, counter: {counter:?}");
419 counter
423 .add(1)
424 .inspect_err(|err| {
426 log_error!("run_utc_timeline_monitor: could not increment counter: {err:?}")
427 })
428 .unwrap_or(());
429 }
430 },
431 result = interest_fut => {
432 match result {
433 Some(interest) => {
434 log_debug!("interest change: {counter:?}, interest: {interest:?}");
435 interested = interest;
436 }
437 None => {
438 log_debug!("no longer needs counter monitoring: {counter:?}");
439 break;
440 }
441 }
442 },
443 };
444 }
445 log_debug!("run_utc_timeline_monitor: monitoring UTC clock timeline changes: exit");
446}
447
448pub struct HrTimerManager {
452 state: LockDepMutex<HrTimerManagerState, HrTimerManagerStateLock>,
453
454 start_next_sender: OnceLock<UnboundedSender<Cmd>>,
457}
458pub type HrTimerManagerHandle = Arc<HrTimerManager>;
459
460impl HrTimerManager {
461 pub fn new(parent_node: &fuchsia_inspect::Node) -> HrTimerManagerHandle {
462 let inspect_node = parent_node.create_child("hr_timer_manager");
463 let new_manager = Arc::new(Self {
464 state: HrTimerManagerState::new(&inspect_node).into(),
465 start_next_sender: Default::default(),
466 });
467 let manager_weak = Arc::downgrade(&new_manager);
468
469 inspect_node.record_lazy_child("hr_timer_manager", move || {
471 let manager_ref = manager_weak.upgrade().expect("inner HrTimerManager");
472 async move {
473 let now = zx::BootInstant::get();
476
477 let inspector = fuchsia_inspect::Inspector::default();
478 inspector.root().record_int("now_ns", now.into_nanos());
479
480 let (
481 timers,
482 pending_timers_count,
483 message_counter,
484 loop_started,
485 loop_completed,
486 debug_start_stage_counter,
487 ) = {
488 let guard = manager_ref.lock();
489 (
490 guard
491 .pending_timers
492 .iter()
493 .map(|(k, v)| (*k, v.deadline))
494 .collect::<Vec<_>>(),
495 guard.get_pending_timers_count(),
496 guard.message_counter.as_ref().map(|c| c.to_string()).unwrap_or_default(),
497 guard.last_loop_started_timestamp,
498 guard.last_loop_completed_timestamp,
499 guard.debug_start_stage_counter,
500 )
501 };
502 inspector.root().record_uint("pending_timers_count", pending_timers_count as u64);
503 inspector.root().record_string("message_counter", message_counter);
504
505 let deadlines = inspector.root().create_string_array("timers", timers.len());
508 for (i, (k, v)) in timers.into_iter().enumerate() {
509 let remaining = v.estimate_boot().unwrap() - now;
510 deadlines.set(
511 i,
512 format!(
513 "{k:?} -> {v} ns (remains: {})",
514 time_pretty::format_duration(remaining)
515 ),
516 );
517 }
518 inspector.root().record(deadlines);
519
520 inspector.root().record_int("last_loop_started_at_ns", loop_started.into_nanos());
521 inspector
522 .root()
523 .record_int("last_loop_completed_at_ns", loop_completed.into_nanos());
524 inspector
525 .root()
526 .record_uint("debug_start_stage_counter", debug_start_stage_counter);
527
528 {
529 let guard = manager_ref.lock();
530 guard.record_events(inspector.root());
531 }
532
533 Ok(inspector)
534 }
535 .boxed()
536 });
537 parent_node.record(inspect_node);
538 new_manager
539 }
540
541 fn get_sender(&self) -> UnboundedSender<Cmd> {
544 self.start_next_sender.get().expect("start_next_sender is initialized").clone()
545 }
546
547 pub fn get_timeline_change_observer(
552 &self,
553 timer: &HrTimerHandle,
554 ) -> Result<TimelineChangeObserver, Errno> {
555 let timer_id = timer.get_id();
556 let counter = zx::Counter::create();
557 let counter_clone = counter
558 .duplicate_handle(zx::Rights::SAME_RIGHTS)
559 .map_err(|status| from_status_like_fdio!(status))
560 .map_err(|err| {
561 log_error!("could not duplicate handle: {err:?}");
562 errno!(EINVAL, format!("could not duplicate handle: {err}, {timer_id:?}"))
563 })?;
564 let (send, recv) = mpsc::unbounded();
565 self.get_sender()
566 .unbounded_send(Cmd::MonitorUtc { timer: timer.clone(), counter, recv })
567 .map_err(|err| {
568 log_error!("could not send: {err:?}");
569 errno!(EINVAL, format!("could not send Cmd::Monitor: {err}, {timer_id:?}"))
570 })?;
571 Ok(TimelineChangeObserver::new(counter_clone, send))
572 }
573
574 pub fn init(self: &HrTimerManagerHandle, system_task: &CurrentTask) -> Result<(), Errno> {
576 self.init_internal(
577 system_task,
578 None,
579 None,
580 )
581 }
582
583 fn init_internal(
585 self: &HrTimerManagerHandle,
586 system_task: &CurrentTask,
587 wake_channel_for_test: Option<zx::Channel>,
589 message_counter_for_test: Option<zx::Counter>,
591 ) -> Result<(), Errno> {
592 let (start_next_sender, start_next_receiver) = mpsc::unbounded();
593 self.start_next_sender.set(start_next_sender).map_err(|_| errno!(EEXIST))?;
594
595 let self_ref = self.clone();
596
597 let setup_done = zx::Event::create();
600 let setup_done_clone = setup_done
601 .duplicate_handle(zx::Rights::SAME_RIGHTS)
602 .map_err(|status| from_status_like_fdio!(status))?;
603
604 let closure = async move |locked_and_task: LockedAndTask<'_>| {
605 let current_thread = std::thread::current();
606 log_info!(
608 "hr_timer_manager thread: {:?} ({:?})",
609 current_thread.name(),
610 current_thread.id()
611 );
612 if let Err(e) = self_ref
613 .watch_new_hrtimer_loop(
614 locked_and_task.current_task(),
615 start_next_receiver,
616 wake_channel_for_test,
617 message_counter_for_test,
618 Some(setup_done_clone),
619 )
620 .await
621 {
622 log_error!("while running watch_new_hrtimer_loop: {e:?}");
623 }
624 log_warn!("hr_timer_manager: finished kernel thread. should never happen in prod code");
625 };
626 let req = SpawnRequestBuilder::new()
627 .with_debug_name("hr-timer-manager")
628 .with_async_closure(closure)
629 .build();
630 system_task.kernel().kthreads.spawner().spawn_from_request(req);
631 log_info!("hr_timer_manager: waiting on setup done");
632 wait_signaled_sync(&setup_done)
633 .to_result()
634 .map_err(|status| from_status_like_fdio!(status))?;
635 log_info!("hr_timer_manager: setup done");
636
637 Ok(())
638 }
639
640 fn notify_timer(
648 self: &HrTimerManagerHandle,
649 system_task: &CurrentTask,
650 triggered_node: &HrTimerNodeHandle,
651 lease: zx::EventPair,
652 ) -> Result<bool> {
653 let timer_id = triggered_node.hr_timer.get_id();
654 {
655 let guard = self.lock();
656 if let Some(active_state) = guard.pending_timers.get(&timer_id) {
657 if !Arc::ptr_eq(&active_state.node, triggered_node) {
662 log_debug!("notify_timer: ignoring stale alarm for timer_id: {:?}", timer_id);
663 return Ok(false);
664 }
665 } else {
666 log_debug!(
667 "notify_timer: ignoring alarm for timer_id: {:?} (not in pending_timers)",
668 timer_id
669 );
670 return Ok(false);
671 }
672 }
673
674 log_debug!("watch_new_hrtimer_loop: Cmd::Alarm: triggered alarm: {:?}", timer_id);
675 ftrace::duration!("alarms", "starnix:hrtimer:notify_timer", "timer_id" => timer_id);
676 self.lock().pending_timers.remove(&timer_id).map(|s| s.task.detach());
677 signal_event(
678 &triggered_node.hr_timer.event(),
679 zx::Signals::NONE,
680 zx::Signals::TIMER_SIGNALED,
681 )
682 .context("notify_timer: hrtimer signal handle")?;
683
684 let wake_source = triggered_node.wake_source.clone();
686 if let Some(wake_source) = wake_source.as_ref().and_then(|f| f.upgrade()) {
687 let lease_token = lease.into_handle();
688 wake_source.on_wake(system_task, &lease_token);
691 drop(lease_token);
694 }
695 ftrace::instant!(
696 "alarms",
697 "starnix:hrtimer:notify_timer:drop_lease",
698 ftrace::Scope::Process,
699 "timer_id" => timer_id
700 );
701 Ok(true)
702 }
703
704 fn inject_or_set_message_counter(
707 self: &HrTimerManagerHandle,
708 message_counter: OwnedMessageCounterHandle,
709 ) {
710 let mut guard = self.lock();
711 if guard.message_counter.is_none() {
712 guard.message_counter = Some(message_counter);
713 }
714 }
715
716 fn record_inspect_on_stop(
717 self: &HrTimerManagerHandle,
718 guard: &mut LockDepGuard<'_, HrTimerManagerState>,
719 prev_len: usize,
720 koid: zx::Koid,
721 ) {
722 let after_len = guard.get_pending_timers_count();
723 let inspect_event_type = if after_len == prev_len {
724 None
725 } else if after_len == prev_len - 1 {
726 Some(InspectHrTimerEvent::Remove(koid))
727 } else {
728 Some(InspectHrTimerEvent::retain_err(prev_len, after_len, "removing timer"))
729 };
730 if let Some(inspect_event_type) = inspect_event_type {
731 self.record_event(guard, inspect_event_type, None);
732 }
733 }
734
735 fn record_inspect_on_alarm(
736 self: &HrTimerManagerHandle,
737 guard: &mut LockDepGuard<'_, HrTimerManagerState>,
738 timer_id: zx::Koid,
739 deadline: TargetTime,
740 ) {
741 self.record_event(guard, InspectHrTimerEvent::Alarm(timer_id), Some(deadline));
742 }
743
744 fn record_inspect_on_start(
745 self: &HrTimerManagerHandle,
746 guard: &mut LockDepGuard<'_, HrTimerManagerState>,
747 timer_id: zx::Koid,
748 task: fasync::Task<()>,
749 deadline: TargetTime,
750 node: HrTimerNodeHandle,
751 prev_len: usize,
752 ) {
753 guard
754 .pending_timers
755 .insert(timer_id, TimerState { task, deadline, node })
756 .map(|timer_state| {
757 log_debug!(
760 "watch_new_hrtimer_loop: removing timer task in Cmd::Start: {:?}",
761 timer_state
762 );
763 timer_state
764 })
765 .map(|v| v.task.detach());
766
767 let after_len = guard.get_pending_timers_count();
769 let inspect_event_type = if after_len == prev_len {
770 InspectHrTimerEvent::Update(timer_id)
771 } else if after_len == prev_len + 1 {
772 InspectHrTimerEvent::Add(timer_id)
773 } else {
774 InspectHrTimerEvent::retain_err(prev_len, after_len, "adding timer")
775 };
776 self.record_event(guard, inspect_event_type, Some(deadline));
777 }
778
779 async fn watch_new_hrtimer_loop(
789 self: &HrTimerManagerHandle,
790 system_task: &CurrentTask,
791 mut start_next_receiver: UnboundedReceiver<Cmd>,
792 mut wake_channel_for_test: Option<zx::Channel>,
793 message_counter_for_test: Option<zx::Counter>,
794 setup_done: Option<zx::Event>,
795 ) -> Result<()> {
796 self.lock().debug_start_stage_counter = 1005;
800 ftrace::instant!("alarms", "watch_new_hrtimer_loop:init", ftrace::Scope::Process);
801 defer! {
802 log_warn!("watch_new_hrtimer_loop: exiting. This should only happen in tests.");
803 }
804
805 let (device_channel, message_counter) = {
806 defer! {
807 setup_done
810 .as_ref()
811 .map(|e| signal_event(e, zx::Signals::NONE, zx::Signals::EVENT_SIGNALED));
812 }
813 let wake_channel = wake_channel_for_test.take().unwrap_or_else(|| {
814 connect_to_wake_alarms_async().expect("connection to wake alarms async proxy")
815 });
816 self.lock().debug_start_stage_counter = 1004;
817
818 let counter_name = "wake-alarms";
819 let (device_channel, counter) = if let Some(message_counter) = message_counter_for_test
820 {
821 (wake_channel, message_counter)
823 } else {
824 create_proxy_for_wake_events_counter_zero(wake_channel, counter_name.to_string())
825 };
826 self.lock().debug_start_stage_counter = 1003;
827 let message_counter = system_task
828 .kernel()
829 .suspend_resume_manager
830 .add_message_counter(counter_name, Some(counter));
831 self.inject_or_set_message_counter(message_counter.clone());
832 (device_channel, message_counter)
833 };
834
835 self.lock().debug_start_stage_counter = 1002;
836 let device_async_proxy =
837 fta::WakeAlarmsProxy::new(fidl::AsyncChannel::from_channel(device_channel));
838
839 let mut interval_timers_pending_reschedule: HashMap<zx::Koid, SharedMessageCounter> =
845 HashMap::new();
846
847 let mut task_by_timer_id: HashMap<zx::Koid, fasync::Task<()>> = HashMap::new();
849
850 self.lock().debug_start_stage_counter = 1001;
851 ftrace::instant!("alarms", "watch_new_hrtimer_loop:init_done", ftrace::Scope::Process);
852 while let Some(cmd) = start_next_receiver.next().await {
853 {
854 let mut guard = self.lock();
855 guard.debug_start_stage_counter = 1002;
856 guard.last_loop_started_timestamp = zx::BootInstant::get();
857 }
858 ftrace::duration!("alarms", "start_next_receiver:loop");
859
860 log_debug!("watch_new_hrtimer_loop: got command: {cmd:?}");
861 self.lock().debug_start_stage_counter = 0;
862 match cmd {
863 Cmd::Start { new_timer_node, done, message_counter } => {
867 self.lock().debug_start_stage_counter = 1;
868 defer! {
869 let _ = signal_event(&done, zx::Signals::NONE, zx::Signals::EVENT_SIGNALED)
871 .map_err(|err| to_errno_with_log(err));
872 }
873
874 let hr_timer = &new_timer_node.hr_timer;
875 let timer_id = hr_timer.get_id();
876 let wake_alarm_id = hr_timer.wake_alarm_id();
877 let trace_id = hr_timer.trace_id();
878 log_debug!(
879 "watch_new_hrtimer_loop: Cmd::Start: timer_id: {:?}, wake_alarm_id: {}",
880 timer_id,
881 wake_alarm_id
882 );
883 ftrace::duration!("alarms", "starnix:hrtimer:start", "timer_id" => timer_id);
884 ftrace::flow_begin!("alarms", "hrtimer_lifecycle", trace_id);
885
886 let (prev_len, maybe_cancel) = {
887 let mut guard = self.lock();
888 guard.debug_start_stage_counter = 2;
891 let prev_len = guard.get_pending_timers_count();
893 let maybe_cancel = guard.pending_timers.remove(&timer_id);
894 (prev_len, maybe_cancel)
895 };
896 log_long_op!(cancel_by_id(
897 &message_counter,
898 maybe_cancel,
899 &timer_id,
900 &device_async_proxy,
901 &mut interval_timers_pending_reschedule,
902 &mut task_by_timer_id,
903 &wake_alarm_id,
904 ));
905 ftrace::instant!("alarms", "starnix:hrtimer:cancel_pre_start", ftrace::Scope::Process, "timer_id" => timer_id);
906
907 let setup_event = zx::Event::create();
910 let deadline = new_timer_node.deadline;
911
912 ftrace::duration!("alarms", "starnix:hrtimer:signaled", "timer_id" => timer_id);
913
914 self.lock().debug_start_stage_counter = 3;
915 let request_fut = match deadline {
919 TargetTime::Monotonic(_) => {
920 panic!("can not schedule wake alarm on monotonic timeline")
922 }
923 TargetTime::BootInstant(boot_instant) => device_async_proxy.set_and_wait(
924 boot_instant,
925 fta::SetMode::NotifySetupDone(
926 setup_event
927 .duplicate_handle(zx::Rights::SAME_RIGHTS)
928 .map_err(|status| from_status_like_fdio!(status))?,
929 ),
930 &wake_alarm_id,
931 ),
932 TargetTime::RealTime(utc_instant) => device_async_proxy.set_and_wait_utc(
933 &fta::InstantUtc { timestamp_utc: utc_instant.into_nanos() },
934 fta::SetMode::NotifySetupDone(
935 setup_event
936 .duplicate_handle(zx::Rights::SAME_RIGHTS)
937 .map_err(|status| from_status_like_fdio!(status))?,
938 ),
939 &wake_alarm_id,
940 ),
941 };
942 let mut done_sender = self.get_sender();
943
944 self.lock().debug_start_stage_counter = 4;
945 let self_clone = self.clone();
946 let new_timer_node_clone = new_timer_node.clone();
947 let task = fasync::Task::local(async move {
948 log_debug!(
949 "wake_alarm_future: set_and_wait will block here: {wake_alarm_id:?}"
950 );
951 ftrace::instant!("alarms", "starnix:hrtimer:wait", ftrace::Scope::Process, "timer_id" => timer_id);
952 ftrace::flow_step!("alarms", "hrtimer_lifecycle", trace_id);
953
954 let response = request_fut.await;
956
957 let message_counter = self_clone.lock().share_message_counter(false);
959 ftrace::instant!("alarms", "starnix:hrtimer:wake", ftrace::Scope::Process, "timer_id" => timer_id);
960
961 log_debug!("wake_alarm_future: set_and_wait over: {:?}", response);
962 match response {
963 Ok(Ok(lease)) => {
967 log_long_op!(done_sender.send(Cmd::Alarm {
968 new_timer_node: new_timer_node_clone,
969 lease,
970 message_counter
971 }))
972 .expect("infallible");
973 }
974 Ok(Err(error)) => {
975 ftrace::duration!("alarms", "starnix:hrtimer:wake_error", "timer_id" => timer_id);
976 log_debug!(
977 "wake_alarm_future: protocol error: {error:?}: timer_id: {timer_id:?}"
978 );
979 let mut guard = self_clone.lock();
980 let pending = &mut guard.pending_timers;
981 process_alarm_protocol_error(pending, &timer_id, error);
982 }
983 Err(error) => {
984 ftrace::duration!("alarms", "starnix:hrtimer:fidl_error", "timer_id" => timer_id);
985 log_debug!(
986 "wake_alarm_future: FIDL error: {error:?}: timer_id: {timer_id:?}"
987 );
988 self_clone.lock().pending_timers.remove(&timer_id);
989 }
990 }
991 log_debug!("wake_alarm_future: closure done for timer_id: {timer_id:?}");
992 });
993 self.lock().debug_start_stage_counter = 5;
994 ftrace::instant!("alarms", "starnix:hrtimer:pre_setup_event_signal", ftrace::Scope::Process, "timer_id" => timer_id);
995
996 match log_long_op!(wait_signaled(&setup_event)) {
999 Ok(_) => {
1000 ftrace::instant!("alarms", "starnix:hrtimer:setup_event_signaled", ftrace::Scope::Process, "timer_id" => timer_id);
1001 let mut guard = self.lock();
1002 guard.debug_start_stage_counter = 6;
1003 self.record_inspect_on_start(
1004 &mut guard,
1005 timer_id,
1006 task,
1007 deadline,
1008 new_timer_node,
1009 prev_len,
1010 );
1011 log_debug!("Cmd::Start scheduled: timer_id: {:?}", timer_id);
1012 }
1013 Err(err) => {
1014 ftrace::instant!("alarms", "starnix:hrtimer:setup_event_error", ftrace::Scope::Process, "timer_id" => timer_id);
1015 to_errno_with_log(err);
1016 }
1017 }
1018 self.lock().debug_start_stage_counter = 999;
1019 }
1020 Cmd::Alarm { new_timer_node, lease, message_counter } => {
1021 self.lock().debug_start_stage_counter = 10;
1022 let timer = &new_timer_node.hr_timer;
1023 let timer_id = timer.get_id();
1024 let deadline = new_timer_node.deadline;
1025 ftrace::duration!("alarms", "starnix:hrtimer:alarm", "timer_id" => timer_id);
1026 ftrace::flow_step!("alarms", "hrtimer_lifecycle", timer.trace_id());
1027 match self.notify_timer(system_task, &new_timer_node, lease) {
1028 Ok(true) => {
1029 if *timer.is_interval.lock() {
1035 interval_timers_pending_reschedule
1036 .insert(timer_id, message_counter);
1037 }
1038 }
1039 Ok(false) => {
1040 }
1042 Err(e) => {
1043 log_error!("watch_new_hrtimer_loop: notify_timer failed: {e:?}");
1044 }
1045 }
1046 log_debug!("Cmd::Alarm done: timer_id: {timer_id:?}");
1051 {
1052 let mut guard = self.lock();
1053 guard.debug_start_stage_counter = 19;
1054 self.record_inspect_on_alarm(&mut guard, timer_id, deadline);
1055 }
1056 }
1057 Cmd::Stop { timer, done, message_counter } => {
1058 self.lock().debug_start_stage_counter = 20;
1059 defer! {
1060 let _ = signal_event(&done, zx::Signals::NONE, zx::Signals::EVENT_SIGNALED)
1061 .map_err(|err| to_errno_with_log(err));
1062 }
1063 let timer_id = timer.get_id();
1064 log_debug!("watch_new_hrtimer_loop: Cmd::Stop: timer_id: {:?}", timer_id);
1065 ftrace::duration!("alarms", "starnix:hrtimer:stop", "timer_id" => timer_id);
1066 ftrace::flow_step!("alarms", "hrtimer_lifecycle", timer.trace_id());
1067
1068 let (maybe_cancel, prev_len) = {
1069 let mut guard = self.lock();
1070 let prev_len = guard.get_pending_timers_count();
1071 (guard.pending_timers.remove(&timer_id), prev_len)
1072 };
1073
1074 let wake_alarm_id = timer.wake_alarm_id();
1075 log_long_op!(cancel_by_id(
1076 &message_counter,
1077 maybe_cancel,
1078 &timer_id,
1079 &device_async_proxy,
1080 &mut interval_timers_pending_reschedule,
1081 &mut task_by_timer_id,
1082 &wake_alarm_id,
1083 ));
1084 ftrace::instant!("alarms", "starnix:hrtimer:cancel_at_stop", ftrace::Scope::Process, "timer_id" => timer_id);
1085
1086 {
1087 let mut guard = self.lock();
1088 self.record_inspect_on_stop(&mut guard, prev_len, timer_id);
1089 }
1090 log_debug!("Cmd::Stop done: {timer_id:?}");
1091 self.lock().debug_start_stage_counter = 29;
1092 }
1093 Cmd::MonitorUtc { timer, counter, recv } => {
1094 self.lock().debug_start_stage_counter = 30;
1095 ftrace::duration!("alarms", "starnix:hrtimer:monitor_utc", "timer_id" => timer.get_id());
1096 ftrace::flow_step!("alarms", "hrtimer_lifecycle", timer.trace_id());
1097 let monitor_task = fasync::Task::local(async move {
1098 run_utc_timeline_monitor(counter, recv).await;
1099 });
1100 task_by_timer_id.insert(timer.get_id(), monitor_task);
1101 self.lock().debug_start_stage_counter = 39;
1102 }
1103 }
1104 let mut guard = self.lock();
1105 guard.debug_start_stage_counter = 90;
1106
1107 log_debug!(
1108 "watch_new_hrtimer_loop: pending timers count: {}",
1109 guard.pending_timers.len()
1110 );
1111 log_debug!("watch_new_hrtimer_loop: pending timers: {:?}", guard.pending_timers);
1112 log_debug!(
1113 "watch_new_hrtimer_loop: message counter: {:?}",
1114 message_counter.to_string(),
1115 );
1116 log_debug!(
1117 "watch_new_hrtimer_loop: interval timers: {:?}",
1118 interval_timers_pending_reschedule.len(),
1119 );
1120
1121 guard.last_loop_completed_timestamp = zx::BootInstant::get();
1122 guard.debug_start_stage_counter = 99;
1123 } Ok(())
1126 }
1127
1128 fn lock(&self) -> LockDepGuard<'_, HrTimerManagerState> {
1129 self.state.lock()
1130 }
1131
1132 fn record_event(
1133 self: &HrTimerManagerHandle,
1134 guard: &mut LockDepGuard<'_, HrTimerManagerState>,
1135 event_type: InspectHrTimerEvent,
1136 deadline: Option<TargetTime>,
1137 ) {
1138 if guard.events.len() >= INSPECT_EVENT_BUFFER_SIZE {
1139 guard.events.pop_front();
1140 }
1141 guard.events.push_back(InspectEvent::new(event_type, deadline));
1142 }
1143
1144 pub fn add_timer(
1148 self: &HrTimerManagerHandle,
1149 wake_source: Option<Weak<dyn OnWakeOps>>,
1150 new_timer: &HrTimerHandle,
1151 deadline: TargetTime,
1152 ) -> Result<(), Errno> {
1153 log_debug!("add_timer: entry: {new_timer:?}, deadline: {deadline:?}");
1154 ftrace::duration!("alarms", "starnix:add_timer", "deadline" => deadline.estimate_boot().unwrap().into_nanos());
1155 ftrace::flow_step!("alarms", "hrtimer_lifecycle", new_timer.trace_id());
1156
1157 let message_counter_until_timer_scheduled = self.lock().share_message_counter(true);
1159
1160 let sender = self.get_sender();
1161 let new_timer_node = HrTimerNode::new(deadline, wake_source, new_timer.clone());
1162 let wake_alarm_scheduled = zx::Event::create();
1163 let wake_alarm_scheduled_clone = wake_alarm_scheduled
1164 .duplicate_handle(zx::Rights::SAME_RIGHTS)
1165 .map_err(|status| from_status_like_fdio!(status))?;
1166 let timer_id = new_timer.get_id();
1167 sender
1168 .unbounded_send(Cmd::Start {
1169 new_timer_node,
1170 message_counter: message_counter_until_timer_scheduled,
1171 done: wake_alarm_scheduled_clone,
1172 })
1173 .map_err(|_| errno!(EINVAL, "add_timer: could not send Cmd::Start"))?;
1174
1175 wait_signaled_sync(&wake_alarm_scheduled)
1177 .map_err(|_| errno!(EINVAL, "add_timer: wait_signaled_sync failed"))?;
1178
1179 log_debug!("add_timer: exit : timer_id: {timer_id:?}");
1180 Ok(())
1181 }
1182
1183 pub fn remove_timer(self: &HrTimerManagerHandle, timer: &HrTimerHandle) -> Result<(), Errno> {
1187 log_debug!("remove_timer: entry: {timer:?}");
1188 ftrace::duration!("alarms", "starnix:remove_timer");
1189 let message_counter_until_removed = self.lock().share_message_counter(true);
1191
1192 let sender = self.get_sender();
1193 let done = zx::Event::create();
1194 let done_clone = done
1195 .duplicate_handle(zx::Rights::SAME_RIGHTS)
1196 .map_err(|status| from_status_like_fdio!(status))?;
1197 let timer_id = timer.get_id();
1198 sender
1199 .unbounded_send(Cmd::Stop {
1200 timer: timer.clone(),
1201 message_counter: message_counter_until_removed,
1202 done: done_clone,
1203 })
1204 .map_err(|_| errno!(EINVAL, "remove_timer: could not send Cmd::Stop"))?;
1205
1206 wait_signaled_sync(&done)
1208 .map_err(|_| errno!(EINVAL, "add_timer: wait_signaled_sync failed"))?;
1209 log_debug!("remove_timer: exit: {timer_id:?}");
1210 Ok(())
1211 }
1212}
1213
1214#[derive(Debug)]
1215pub struct HrTimer {
1216 event: zx::Event,
1218
1219 event_koid: zx::Koid,
1222
1223 pub is_interval: LockDepMutex<bool, HrTimerIsIntervalLock>,
1234}
1235pub type HrTimerHandle = Arc<HrTimer>;
1236
1237impl Drop for HrTimer {
1238 fn drop(&mut self) {
1239 let wake_alarm_id = self.wake_alarm_id();
1240 ftrace::duration!("alarms", "hrtimer::drop", "timer_id" => self.get_id(), "wake_alarm_id" => &wake_alarm_id[..]);
1241 ftrace::flow_end!("alarms", "hrtimer_lifecycle", self.trace_id());
1242 }
1243}
1244
1245impl HrTimer {
1246 pub fn new() -> HrTimerHandle {
1247 let event = zx::Event::create();
1248 let event_koid = event.koid().expect("infallible");
1249 let ret = Arc::new(Self { event, event_koid, is_interval: false.into() });
1250 let wake_alarm_id = ret.wake_alarm_id();
1251 ftrace::duration!("alarms", "hrtimer::new", "timer_id" => ret.get_id(), "wake_alarm_id" => &wake_alarm_id[..]);
1252 ftrace::flow_begin!("alarms", "hrtimer_lifecycle", ret.trace_id(), "wake_alarm_id" => &wake_alarm_id[..]);
1253 ret
1254 }
1255
1256 pub fn event(&self) -> zx::Event {
1257 self.event
1258 .duplicate_handle(zx::Rights::SAME_RIGHTS)
1259 .expect("Duplicate hrtimer event handle")
1260 }
1261
1262 pub fn get_id(&self) -> zx::Koid {
1266 self.event_koid
1267 }
1268
1269 fn wake_alarm_id(&self) -> String {
1274 let i = if *self.is_interval.lock() { "i1" } else { "i0" };
1275 let koid = self.get_id();
1276 format!("starnix:{koid:?}:{i}")
1277 }
1278
1279 fn trace_id(&self) -> ftrace::Id {
1280 self.get_id().raw_koid().into()
1281 }
1282}
1283
1284impl TimerOps for HrTimerHandle {
1285 fn start(
1286 &self,
1287 current_task: &CurrentTask,
1288 source: Option<Weak<dyn OnWakeOps>>,
1289 deadline: TargetTime,
1290 ) -> Result<(), Errno> {
1291 signal_event(&self.event, zx::Signals::TIMER_SIGNALED, zx::Signals::NONE)
1293 .map_err(|status| from_status_like_fdio!(status))?;
1294 current_task.kernel().hrtimer_manager.add_timer(
1295 source,
1296 self,
1297 deadline.into_resolved_utc_deadline(),
1298 )?;
1299 Ok(())
1300 }
1301
1302 fn stop(&self, kernel: &Arc<Kernel>) -> Result<(), Errno> {
1303 signal_event(&self.event, zx::Signals::TIMER_SIGNALED, zx::Signals::NONE)
1305 .map_err(|status| from_status_like_fdio!(status))?;
1306 Ok(kernel.hrtimer_manager.remove_timer(self)?)
1307 }
1308
1309 fn as_handle_ref(&self) -> HandleRef<'_> {
1310 self.event.as_handle_ref()
1311 }
1312
1313 fn get_timeline_change_observer(
1314 &self,
1315 current_task: &CurrentTask,
1316 ) -> Option<TimelineChangeObserver> {
1317 current_task
1319 .kernel()
1320 .hrtimer_manager
1321 .get_timeline_change_observer(self)
1322 .inspect_err(|err| {
1323 log_error!("hr_timer_manager: could not create timeline change counter: {err:?}")
1324 })
1325 .ok()
1326 }
1327}
1328
1329#[derive(Clone, Debug)]
1331struct HrTimerNode {
1332 deadline: TargetTime,
1334
1335 wake_source: Option<Weak<dyn OnWakeOps>>,
1341
1342 hr_timer: HrTimerHandle,
1344}
1345type HrTimerNodeHandle = Arc<HrTimerNode>;
1346
1347impl HrTimerNode {
1348 fn new(
1349 deadline: TargetTime,
1350 wake_source: Option<Weak<dyn OnWakeOps>>,
1351 hr_timer: HrTimerHandle,
1352 ) -> HrTimerNodeHandle {
1353 Arc::new(Self { deadline, wake_source, hr_timer })
1354 }
1355}
1356
1357#[cfg(test)]
1358mod tests {
1359 use super::*;
1360 use crate::testing::spawn_kernel_and_run;
1361 use crate::time::HrTimer;
1362 use fake_wake_alarms::{MAGIC_EXPIRE_DEADLINE, Response, serve_fake_wake_alarms};
1363 use fidl_fuchsia_time_alarms as fta;
1364 use fuchsia_async as fasync;
1365 use fuchsia_runtime::{UtcClockUpdate, UtcInstant};
1366 use std::sync::LazyLock;
1367 use std::thread;
1368
1369 static CLOCK_OPTS: LazyLock<zx::ClockOpts> = LazyLock::new(zx::ClockOpts::empty);
1370 const BACKSTOP_TIME: UtcInstant = UtcInstant::from_nanos(222222);
1371
1372 fn create_utc_clock_for_test() -> UtcClock {
1373 let clock = UtcClock::create(*CLOCK_OPTS, Some(BACKSTOP_TIME)).unwrap();
1374 clock.update(UtcClockUpdate::builder().approximate_value(BACKSTOP_TIME)).unwrap();
1375 clock
1376 }
1377
1378 impl HrTimerManagerState {
1379 fn new_for_test() -> Self {
1380 Self {
1381 events: VecDeque::with_capacity(INSPECT_EVENT_BUFFER_SIZE),
1382 pending_timers: Default::default(),
1383 message_counter: None,
1384 last_loop_started_timestamp: zx::BootInstant::INFINITE_PAST,
1385 last_loop_completed_timestamp: zx::BootInstant::INFINITE_PAST,
1386 debug_start_stage_counter: 0,
1387 }
1388 }
1389 }
1390
1391 fn connect_factory(message_counter: zx::Counter, response_type: Response) -> zx::Channel {
1393 let (client, server) = zx::Channel::create();
1394
1395 let _detached = thread::spawn(move || {
1397 fasync::LocalExecutor::default().run_singlethreaded(async move {
1398 let stream =
1399 fidl::endpoints::ServerEnd::<fta::WakeAlarmsMarker>::new(server).into_stream();
1400 serve_fake_wake_alarms(message_counter, response_type, stream, false)
1401 .await;
1402 });
1403 });
1404 client
1405 }
1406
1407 fn init_hr_timer_manager(
1415 current_task: &CurrentTask,
1416 response_type: Response,
1417 ) -> (HrTimerManagerHandle, zx::Counter) {
1418 let manager = Arc::new(HrTimerManager {
1419 state: HrTimerManagerState::new_for_test().into(),
1420 start_next_sender: Default::default(),
1421 });
1422 let counter = zx::Counter::create();
1423 let counter_clone = counter.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap();
1424 let wake_channel = connect_factory(counter_clone, response_type);
1425 let counter_clone = counter.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap();
1426 manager
1427 .init_internal(¤t_task, Some(wake_channel), Some(counter_clone))
1428 .expect("infallible");
1429 (manager, counter)
1430 }
1431
1432 #[fuchsia::test]
1433 async fn test_triggering() {
1434 spawn_kernel_and_run(async |_, current_task| {
1435 let (manager, counter) = init_hr_timer_manager(current_task, Response::Immediate);
1436
1437 let timer1 = HrTimer::new();
1438 let timer2 = HrTimer::new();
1439 let timer3 = HrTimer::new();
1440
1441 manager.add_timer(None, &timer1, zx::BootInstant::from_nanos(1).into()).unwrap();
1442 manager.add_timer(None, &timer2, zx::BootInstant::from_nanos(2).into()).unwrap();
1443 manager.add_timer(None, &timer3, zx::BootInstant::from_nanos(3).into()).unwrap();
1444
1445 wait_signaled_sync(&timer1.event()).to_result().unwrap();
1446 wait_signaled_sync(&timer2.event()).to_result().unwrap();
1447 wait_signaled_sync(&timer3.event()).to_result().unwrap();
1448
1449 assert_eq!(
1450 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1451 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1452 );
1453 })
1454 .await;
1455 }
1456
1457 #[fuchsia::test]
1458 async fn test_triggering_utc() {
1459 spawn_kernel_and_run(async |_, current_task| {
1460 let (manager, counter) = init_hr_timer_manager(current_task, Response::Immediate);
1461
1462 let timer1 = HrTimer::new();
1463 let timer2 = HrTimer::new();
1464 let timer3 = HrTimer::new();
1465
1466 manager.add_timer(None, &timer1, UtcInstant::from_nanos(1).into()).unwrap();
1468 manager.add_timer(None, &timer2, UtcInstant::from_nanos(2).into()).unwrap();
1469 manager.add_timer(None, &timer3, UtcInstant::from_nanos(3).into()).unwrap();
1470
1471 wait_signaled_sync(&timer1.event()).to_result().unwrap();
1472 wait_signaled_sync(&timer2.event()).to_result().unwrap();
1473 wait_signaled_sync(&timer3.event()).to_result().unwrap();
1474
1475 assert_eq!(
1476 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1477 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1478 );
1479 })
1480 .await;
1481 }
1482
1483 #[fuchsia::test]
1484 async fn test_delayed_response() {
1485 spawn_kernel_and_run(async |_, current_task| {
1486 let (manager, counter) = init_hr_timer_manager(current_task, Response::Immediate);
1487
1488 let timer = HrTimer::new();
1489
1490 manager.add_timer(None, &timer, zx::BootInstant::from_nanos(1).into()).unwrap();
1491
1492 assert_eq!(
1493 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1494 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1495 );
1496 })
1497 .await;
1498 }
1499
1500 #[fuchsia::test]
1501 async fn test_protocol_error_response() {
1502 spawn_kernel_and_run(async |_, current_task| {
1503 let (manager, counter) = init_hr_timer_manager(current_task, Response::Error);
1504
1505 let timer = HrTimer::new();
1506 manager.add_timer(None, &timer, zx::BootInstant::from_nanos(1).into()).unwrap();
1507 assert_eq!(
1508 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1509 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1510 );
1511 })
1512 .await;
1513 }
1514
1515 #[fuchsia::test]
1516 async fn reschedule_same_timer() {
1517 spawn_kernel_and_run(async |_, current_task| {
1518 let (manager, counter) = init_hr_timer_manager(current_task, Response::Delayed);
1519
1520 let timer = HrTimer::new();
1521
1522 manager.add_timer(None, &timer, zx::BootInstant::from_nanos(1).into()).unwrap();
1523 manager.add_timer(None, &timer, zx::BootInstant::from_nanos(2).into()).unwrap();
1524
1525 manager
1527 .add_timer(None, &timer, zx::BootInstant::from_nanos(MAGIC_EXPIRE_DEADLINE).into())
1528 .unwrap();
1529 wait_signaled_sync(&timer.event()).to_result().unwrap();
1530
1531 assert_eq!(
1532 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1533 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1534 );
1535 })
1536 .await;
1537 }
1538
1539 #[fuchsia::test]
1540 async fn rescheduling_interval_timers_forbids_suspend() {
1541 spawn_kernel_and_run(async |_, current_task| {
1542 let (hrtimer_manager, counter) = init_hr_timer_manager(current_task, Response::Delayed);
1543
1544 let timer1 = HrTimer::new();
1546 *timer1.is_interval.lock() = true;
1547 hrtimer_manager
1548 .add_timer(None, &timer1, zx::BootInstant::from_nanos(MAGIC_EXPIRE_DEADLINE).into())
1549 .unwrap();
1550 wait_signaled_sync(&timer1.event()).to_result().unwrap();
1551
1552 let timer2 = HrTimer::new();
1554 hrtimer_manager
1555 .add_timer(None, &timer2, zx::BootInstant::from_nanos(MAGIC_EXPIRE_DEADLINE).into())
1556 .unwrap();
1557 wait_signaled_sync(&timer2.event()).to_result().unwrap();
1558
1559 assert_eq!(
1564 counter.wait_one(zx::Signals::COUNTER_POSITIVE, zx::MonotonicInstant::INFINITE),
1565 zx::WaitResult::Ok(zx::Signals::COUNTER_POSITIVE)
1566 );
1567 })
1568 .await;
1569 }
1570
1571 #[fuchsia::test]
1572 async fn canceling_interval_timer_allows_suspend() {
1573 spawn_kernel_and_run(async |_, current_task| {
1574 let (hrtimer_manager, counter) = init_hr_timer_manager(current_task, Response::Delayed);
1575
1576 let timer1 = HrTimer::new();
1577 *timer1.is_interval.lock() = true;
1578 hrtimer_manager
1579 .add_timer(None, &timer1, zx::BootInstant::from_nanos(MAGIC_EXPIRE_DEADLINE).into())
1580 .unwrap();
1581 wait_signaled_sync(&timer1.event()).to_result().unwrap();
1582
1583 assert_eq!(
1585 counter.wait_one(zx::Signals::COUNTER_POSITIVE, zx::MonotonicInstant::INFINITE),
1586 zx::WaitResult::Ok(zx::Signals::COUNTER_POSITIVE)
1587 );
1588
1589 const DURATION_100S: zx::BootDuration = zx::BootDuration::from_seconds(100);
1592 let deadline2: zx::BootInstant = zx::BootInstant::after(DURATION_100S.into());
1593 hrtimer_manager.add_timer(None, &timer1, deadline2.into()).unwrap();
1594
1595 hrtimer_manager.remove_timer(&timer1).unwrap();
1596
1597 assert_eq!(
1599 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1600 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1601 );
1602 })
1603 .await;
1604 }
1605
1606 #[fuchsia::test]
1607 async fn canceling_interval_timer_allows_suspend_with_flake() {
1608 spawn_kernel_and_run(async |_, current_task| {
1609 let (hrtimer_manager, counter) = init_hr_timer_manager(current_task, Response::Delayed);
1610
1611 let timer1 = HrTimer::new();
1612 *timer1.is_interval.lock() = true;
1613 hrtimer_manager
1614 .add_timer(None, &timer1, zx::BootInstant::from_nanos(MAGIC_EXPIRE_DEADLINE).into())
1615 .unwrap();
1616 wait_signaled_sync(&timer1.event()).to_result().unwrap();
1617
1618 assert_eq!(
1619 counter.wait_one(zx::Signals::COUNTER_POSITIVE, zx::MonotonicInstant::INFINITE),
1620 zx::WaitResult::Ok(zx::Signals::COUNTER_POSITIVE)
1621 );
1622 const DURATION_100S: zx::BootDuration = zx::BootDuration::from_seconds(100);
1623 let deadline2: zx::BootInstant = zx::BootInstant::after(DURATION_100S.into());
1624 hrtimer_manager.add_timer(None, &timer1, deadline2.into()).unwrap();
1625 hrtimer_manager.remove_timer(&timer1).unwrap();
1627
1628 assert_eq!(
1629 counter.wait_one(zx::Signals::COUNTER_NON_POSITIVE, zx::MonotonicInstant::INFINITE),
1630 zx::WaitResult::Ok(zx::Signals::COUNTER_NON_POSITIVE)
1631 );
1632 })
1633 .await;
1634 }
1635
1636 #[fuchsia::test]
1637 async fn utc_timeline_monitor_exits_on_interest_drop() {
1638 let counter = zx::Counter::create();
1639 let utc_clock = create_utc_clock_for_test();
1640 let (tx, rx) = mpsc::unbounded();
1641
1642 drop(tx);
1643 run_utc_timeline_monitor_internal(counter, rx, utc_clock).await;
1646 }
1647}