Skip to main content

starnix_core/time/
hr_timer_manager.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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
31/// Max value for inspect event history.
32const 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;
50//
51/// Waits forever synchronously for EVENT_SIGNALED.
52///
53/// For us there is no useful scenario where this wait times out and we can continue operating.
54fn 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        // This is bad and should never happen. If it does, it's a bug that has to be found and
72        // fixed. There is no good way to proceed if these signals are not being signaled properly.
73        log_error!(
74            // Check logs for a `kBadState` status reported from the hrtimer driver.
75            // LINT.IfChange(hrtimer_wait_signaled_sync_tefmo)
76            "wait_signaled_sync: not signaled yet. Report to `componentid:1408151`: result={result:?}",
77            // LINT.ThenChange(//tools/testing/tefmocheck/string_in_log_check.go:hrtimer_wait_signaled_sync_tefmo)
78        );
79        if !logged {
80            #[cfg(all(target_os = "fuchsia", not(doc)))]
81            ::debug::backtrace_request_all_threads();
82            logged = true;
83        }
84    }
85}
86
87/// A macro that waits on a future, but if the future takes longer than
88/// `TIMEOUT_SECONDS`, we log a warning and a stack trace.
89macro_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                    // Check logs for a `kBadState` status reported from the hrtimer driver.
107                    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
120/// Waits forever asynchronously for EVENT_SIGNALED.
121async 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
127/// Cancels an alarm by ID.
128async 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        // Let this task complete and get removed.
139        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 the timer closure complete before continuing.
148        let _ = log_long_op!(timer_state.task);
149    }
150
151    // If this timer is an interval timer, we must remove it from the pending reschedule list.
152    // This does not affect container suspend, since `_message_counter` is live. It's a no-op
153    // for other timers.
154    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
158/// Called when the underlying wake alarms manager reports a fta::WakeAlarmsError
159/// as a result of a call to set_and_wait.
160fn 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            // Do not remove a Dropped timer here, in contrast to other error states: a Dropped
175            // timer is a result of a Stop or a Cancel ahead of a reschedule. In both cases, that
176            // code takes care of removing the timer from the pending timers list.
177            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
188// This function is swapped out for an injected proxy in tests.
189fn 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    // The parameter inside will be used in fmt. But the compiler does not recognize the use when
202    // formatting with the Debug derivative.
203    Add(#[allow(dead_code)] zx::Koid),
204    Update(#[allow(dead_code)] zx::Koid),
205    Remove(#[allow(dead_code)] zx::Koid),
206    // The timer was signaled!
207    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    /// The task that waits for the timer to expire.
241    task: fasync::Task<()>,
242    /// The desired deadline for the timer.
243    deadline: TargetTime,
244    /// The node that represents the current generation of this timer.
245    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    /// All pending timers are stored here.
256    pending_timers: HashMap<zx::Koid, TimerState>,
257
258    /// The event that is registered with runner to allow the hrtimer to wake the kernel.
259    /// Optional, because we want the ability to inject a counter in tests.
260    message_counter: Option<OwnedMessageCounterHandle>,
261
262    /// For recording timer events.
263    events: VecDeque<InspectEvent>,
264
265    /// The last timestamp at which the hrtimer loop was started.
266    last_loop_started_timestamp: zx::BootInstant,
267
268    /// The last timestamp at which the hrtimer loop was completed.
269    last_loop_completed_timestamp: zx::BootInstant,
270
271    // Debug progress counter for Cmd::Start.
272    // TODO: b/454085350 - remove once diagnosed.
273    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            // Initialized later in the State's lifecycle because it only becomes
281            // available after making a connection to the wake proxy.
282            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    /// Gets a new shareable instance of the message counter.
295    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/// Asynchronous commands sent to `watch_new_hrtimer_loop`.
317///
318/// The synchronous methods on HrTimerManager use these commands to communicate
319/// with the alarm manager actor that loops about in `watch_new_hrtimer_loop`.
320///
321/// This allows us to not have to share state between the synchronous and async
322/// methods of `HrTimerManager`.
323#[derive(Debug)]
324enum Cmd {
325    // Start the timer contained in `new_timer_node`.
326    // The processing loop will signal `done` to allow synchronous
327    // return from scheduling an async Cmd::Start.
328    Start {
329        new_timer_node: HrTimerNodeHandle,
330        /// Signaled once the timer is started.
331        done: zx::Event,
332        /// The Starnix container suspend lock. Keep it alive until no more
333        /// work is necessary.
334        message_counter: SharedMessageCounter,
335    },
336    /// Stop the timer noted below. `done` is similar to above.
337    Stop {
338        /// The timer to stop.
339        timer: HrTimerHandle,
340        /// Signaled once the timer is stopped.
341        done: zx::Event,
342        /// The Starnix container suspend lock. Keep it alive until no more
343        /// work is necessary.
344        message_counter: SharedMessageCounter,
345    },
346    /// Triggered by the underlying hrtimer device when an alarm expires.
347    Alarm {
348        /// The affected timer's node.
349        new_timer_node: HrTimerNodeHandle,
350        /// The wake lease provided by the underlying API.
351        lease: zx::EventPair,
352        /// The Starnix container suspend lock. Keep it alive until no more
353        /// work is necessary.
354        message_counter: SharedMessageCounter,
355    },
356    /// Install a timeline change monitor
357    MonitorUtc { timer: HrTimerHandle, counter: zx::Counter, recv: mpsc::UnboundedReceiver<bool> },
358}
359
360// Increments `counter` every time the UTC timeline changes.
361//
362// This counter is shared with UTC timers to provide UTC timeline change notification.
363//
364// Use cases:
365//
366// 1. Counter's value counts the number of times the UTC timeline changed, which is used in timer
367//    `read` calls to report the number of encountered changes, as required by `read`.
368//
369// 2. Counter's `COUNTER_POSITIVE` signal is used in `wait_async` calls on timers, as Starnix must
370//    wake such timers whenever a timeline change happens. The counter reader must reset the
371//    counter to zero after reading its value to allow for a next wake.
372//
373// Other primitives are not appropriate to use here: an Event does not remember how many times it
374// has been signaled, so does not fulfill (1). Atomics don't generate a signal on increment, so
375// don't satisfy (2). Conversely, the `wait_async` machinery on timers can already deal with
376// HandleBased objects, so a Counter can be readily used there.
377async 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
386// See `run_utc_timeline_monitor`.
387// `utc_handle_fn` is useful for injecting in tests.
388async 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        // CLOCK_UPDATED is auto-cleared.
404        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        // Note: all select! branches must allow for exit when their respective futures are
410        // used up.
411        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                    // The consumer of this `counter` should wait for COUNTER_POSITIVE, and
420                    // once it observes the value of the counter, subtract the read value from
421                    // counter.
422                    counter
423                        .add(1)
424                        // Ignore the error after logging it. Should we exit the loop here?
425                        .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
448/// The manager for high-resolution timers.
449///
450/// This manager is responsible for creating and managing high-resolution timers.
451pub struct HrTimerManager {
452    state: LockDepMutex<HrTimerManagerState, HrTimerManagerStateLock>,
453
454    /// The channel sender that notifies the worker thread that HrTimer driver needs to be
455    /// (re)started with a new deadline.
456    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        // Create a lazy inspect node to get HrTimerManager info at read-time.
470        inspect_node.record_lazy_child("hr_timer_manager", move || {
471            let manager_ref = manager_weak.upgrade().expect("inner HrTimerManager");
472            async move {
473                // This gets the clock value directly from the kernel, it is not subject
474                // to the local runner's clock.
475                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                // These are the deadlines we are currently waiting for. The format is:
506                // `alarm koid` -> `deadline nanos` (remains: `duration until alarm nanos`)
507                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    /// Get a copy of a sender channel used for passing async command to the
542    /// event processing loop.
543    fn get_sender(&self) -> UnboundedSender<Cmd> {
544        self.start_next_sender.get().expect("start_next_sender is initialized").clone()
545    }
546
547    /// Returns the counter that tallies the timeline changes of the UTC timeline.
548    ///
549    /// # Args
550    /// - `timer`: the handle of the timer that needs monitoring of timeline changes.
551    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    /// Initialize the [HrTimerManager] in the context of the current system task.
575    pub fn init(self: &HrTimerManagerHandle, system_task: &CurrentTask) -> Result<(), Errno> {
576        self.init_internal(
577            system_task,
578            /*wake_channel_for_test=*/ None,
579            /*message_counter_for_test=*/ None,
580        )
581    }
582
583    // Call this init for testing instead of the one above.
584    fn init_internal(
585        self: &HrTimerManagerHandle,
586        system_task: &CurrentTask,
587        // Can be injected for testing.
588        wake_channel_for_test: Option<zx::Channel>,
589        // Can be injected for testing.
590        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        // Ensure that all internal init has completed in `watch_new_hrtimer_loop`
598        // before proceeding from here.
599        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            // Helps find the thread in backtraces, see wait_signaled_sync.
607            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    /// Notifies `timer` and wake sources about a triggered alarm.
641    ///
642    /// # Returns
643    /// - `Ok(true)` if the alarm was for the current generation and was processed.
644    /// - `Ok(false)` if the alarm was stale. Either the timer was restarted ( via `Cmd:Start`) with
645    ///    the same id before the previous generation's alarm fired, or the timer was stopped
646    ///    (via `Cmd::Stop`) or already processed.
647    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                // Wake source is deliberately not signaled here. When the triggered_node for a
658                // timer_id is not pointer-identical to the one stored in pending_timers, it is a
659                // trigger for some previous generation of timer_id, which has since been
660                // rescheduled.
661                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        // Handle wake source here.
685        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            // `.on_wake` must not block, else the timer management loop will stall.
689            // At the moment `.on_wake`s don't stall at all.
690            wake_source.on_wake(system_task, &lease_token);
691            // Drop the baton lease after wake leases in associated epfd
692            // are activated.
693            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    // If no counter has been injected for tests, set provided `counter` to serve as that
705    // counter. Used to inject a fake counter in tests.
706    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                // This should not happen, at this point we already canceled
758                // any previous instances of the same wake alarm.
759                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        // Record the inspect event
768        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    /// Timer handler loop.
780    ///
781    /// # Args:
782    /// - `wake_channel_for_test`: a channel implementing `fuchsia.time.alarms/Wake`
783    ///   injected by tests only.
784    /// - `message_counter_for_test`: a zx::Counter injected only by tests, to
785    ///   emulate the wake proxy message counter.
786    /// - `setup_done`: signaled once the initial loop setup is complete. Allows
787    ///   pausing any async callers until this loop is in a runnable state.
788    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        // The values assigned to the counter are arbitrary, but unique for each assignment.
797        // This should give us hints as to where any deadlocks might occur if they do.
798        // We also take stack traces, but stack traces do not capture async stacks presently.
799        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                // Ensure that the setup_done event is signaled even if we fail to initialize
808                // correctly. This prevents the caller from blocking forever.
809                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                // For tests only.
822                (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        // Contains suspend locks for interval (periodic) timers that expired, but have not been
840        // rescheduled yet. This allows us to defer container suspend until all such timers have
841        // been rescheduled.
842        // TODO: b/418813184 - Remove in favor of Fuchsia-specific interval timer support
843        // once it is available.
844        let mut interval_timers_pending_reschedule: HashMap<zx::Koid, SharedMessageCounter> =
845            HashMap::new();
846
847        // Per timer tasks.
848        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                // A new timer needs to be started.  The timer node for the timer
864                // is provided, and `done` must be signaled once the setup is
865                // complete.
866                Cmd::Start { new_timer_node, done, message_counter } => {
867                    self.lock().debug_start_stage_counter = 1;
868                    defer! {
869                        // Allow add_timer to proceed once command processing is done.
870                        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                        // Unrelated to prev_len, but convenient to update here since we already
889                        // have `guard`.
890                        guard.debug_start_stage_counter = 2;
891                        // Number of pending timers before any start-related adjustments.
892                        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                    // Signaled when the timer completed setup. We can not forward `done` because
908                    // we have post-schedule work as well.
909                    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                    // Make a request here. Move it into the closure after. Current FIDL semantics
916                    // ensure that even though we do not `.await` on this future, a request to
917                    // schedule a wake alarm based on this timer will be sent.
918                    let request_fut = match deadline {
919                        TargetTime::Monotonic(_) => {
920                            // If we hit this, it's a Starnix bug.
921                            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                        // Wait for this timer to expire. This wait can be arbitrarily long.
955                        let response = request_fut.await;
956
957                        // The counter was already incremented by the wake proxy when the alarm fired.
958                        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                            // Alarm.  This must be processed in the main loop because notification
964                            // requires access to &CurrentTask, which is not available here. So we
965                            // only forward it.
966                            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                    // wait_signaled here should be almost instantaneous.  Blocking for a long time
997                    // here is a bug.
998                    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                            // Alarm was for current generation, success.
1030                            // Interval timers currently need special handling: we must not suspend
1031                            // the container until the interval timer in question gets re-scheduled.
1032                            // To ensure that we stay awake, we store the suspend lock for a while.
1033                            // This prevents container suspend.
1034                            if *timer.is_interval.lock() {
1035                                interval_timers_pending_reschedule
1036                                    .insert(timer_id, message_counter);
1037                            }
1038                        }
1039                        Ok(false) => {
1040                            // Alarm was stale, ignored.
1041                        }
1042                        Err(e) => {
1043                            log_error!("watch_new_hrtimer_loop: notify_timer failed: {e:?}");
1044                        }
1045                    }
1046                    // Interval timers usually reschedule themselves. But if an interval timer
1047                    // is stopped (via Cmd::Stop) or is replaced (via Cmd::Start for the same timer
1048                    // ID) before it has a chance to reschedule, the reschedule lock will get
1049                    // dropped then.
1050                    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        } // while
1124
1125        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    /// Add a new timer.
1145    ///
1146    /// A wake alarm is scheduled for the timer.
1147    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        // Keep system awake until timer is scheduled.
1158        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        // Block until the wake alarm for this timer is scheduled.
1176        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    /// Remove a timer.
1184    ///
1185    /// The timer is removed if scheduled, nothing is changed if it is not.
1186    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        // Keep system awake until timer is removed.
1190        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        // Block until the alarm for this timer is scheduled.
1207        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 used to signal the timer.
1217    event: zx::Event,
1218
1219    // The koid of the `event` above. Cached because calling `koid()` on a
1220    // handle costs a syscall. And yet, the koid is immutable.
1221    event_koid: zx::Koid,
1222
1223    /// True iff the timer is currently set to trigger at an interval.
1224    ///
1225    /// This is used to determine at which point the hrtimer event (not
1226    /// `HrTimer::event` but the one that is shared with the actual driver)
1227    /// should be cleared.
1228    ///
1229    /// If this is true, the timer manager will wait to clear the timer event
1230    /// until the next timer request has been sent to the driver. This prevents
1231    /// lost wake ups where the container happens to suspend between two instances
1232    /// of an interval timer triggering.
1233    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    /// Returns the unique identifier of this [HrTimer].
1263    ///
1264    /// All holders of the same [HrTimerHandle] will see the same value here.
1265    pub fn get_id(&self) -> zx::Koid {
1266        self.event_koid
1267    }
1268
1269    /// Returns the unique alarm ID for this [HrTimer].
1270    ///
1271    /// The naming pattern is: `starnix:Koid(NNNNN):iB`, where `NNNNN` is a koid
1272    /// and B is `1` if the timer is an interval timer, or `0` otherwise.
1273    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        // Before (re)starting the timer, ensure the signal is cleared.
1292        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        // Clear the signal when removing the hrtimer.
1304        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        // Should this return errno instead?
1318        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/// Represents a node of `HrTimer`.
1330#[derive(Clone, Debug)]
1331struct HrTimerNode {
1332    /// The deadline of the associated `HrTimer`.
1333    deadline: TargetTime,
1334
1335    /// The source where initiated this `HrTimer`.
1336    ///
1337    /// When the timer expires, the system will be woken up if necessary. The `on_wake` callback
1338    /// will be triggered with a baton lease to prevent further suspend while Starnix handling the
1339    /// wake event.
1340    wake_source: Option<Weak<dyn OnWakeOps>>,
1341
1342    /// The underlying HrTimer.
1343    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(/*arbitrary*/ 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    // Injected for testing.
1392    fn connect_factory(message_counter: zx::Counter, response_type: Response) -> zx::Channel {
1393        let (client, server) = zx::Channel::create();
1394
1395        // A separate thread is needed to allow independent execution of the server.
1396        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, /*once*/ false)
1401                    .await;
1402            });
1403        });
1404        client
1405    }
1406
1407    // Initializes HrTimerManager for tests.
1408    //
1409    // # Returns
1410    //
1411    // A tuple of:
1412    // - `HrTimerManagerHandle` the unit under test
1413    // - `zx::Counter` a message counter to use in tests to observe suspend state
1414    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(&current_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            // All these are normally already expired as scheduled.
1467            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            // Force alarm expiry.
1526            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            // Schedule an interval timer and let it expire.
1545            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            // Schedule a regular timer and let it expire.
1553            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            // When we have an expired but not rescheduled interval timer (`timer1`), and we have
1560            // an intervening timer that gets scheduled and expires (`timer2`) before `timer1` is
1561            // rescheduled, then suspend should be disallowed (counter > 0) to allow `timer1` to
1562            // be scheduled eventually.
1563            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            // When an interval timer expires, we should not be allowed to suspend.
1584            assert_eq!(
1585                counter.wait_one(zx::Signals::COUNTER_POSITIVE, zx::MonotonicInstant::INFINITE),
1586                zx::WaitResult::Ok(zx::Signals::COUNTER_POSITIVE)
1587            );
1588
1589            // Schedule the same timer again. This time around we do not wait for it to expire,
1590            // but cancel the timer instead.
1591            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            // When we cancel an interval timer, we should be allowed to suspend.
1598            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            // No pause between start and stop has led to flakes before.
1626            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        // Expect that this call returns, when tx no longer exists. Incorrect
1644        // handling of tx closure could cause it to hang otherwise.
1645        run_utc_timeline_monitor_internal(counter, rx, utc_clock).await;
1646    }
1647}