starnix_core/fs/fuchsia/
timer.rs

1// Copyright 2021 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::OnWakeOps;
6use crate::task::{CurrentTask, Kernel};
7use crate::time::TargetTime;
8use crate::time::utc::estimate_boot_deadline_from_utc;
9use crate::vfs::timer::{TimelineChangeObserver, TimerOps};
10use starnix_uapi::errors::Errno;
11use starnix_uapi::{error, from_status_like_fdio};
12use std::sync::{Arc, Weak};
13use zx::HandleRef;
14
15pub struct MonotonicZxTimer {
16    timer: zx::MonotonicTimer,
17}
18
19impl MonotonicZxTimer {
20    pub fn new() -> Self {
21        Self { timer: zx::MonotonicTimer::create() }
22    }
23}
24
25impl TimerOps for MonotonicZxTimer {
26    fn start(
27        &self,
28        current_task: &CurrentTask,
29        _source: Option<Weak<dyn OnWakeOps>>,
30        deadline: TargetTime,
31    ) -> Result<(), Errno> {
32        let timerslack = current_task.read().get_timerslack();
33        match deadline {
34            TargetTime::Monotonic(t) => {
35                self.timer.set(t, timerslack).map_err(|status| from_status_like_fdio!(status))?
36            }
37            TargetTime::BootInstant(_) | TargetTime::RealTime(_) => return error!(EINVAL),
38        };
39
40        Ok(())
41    }
42
43    fn stop(&self, _kernel: &Arc<Kernel>) -> Result<(), Errno> {
44        self.timer.cancel().map_err(|status| from_status_like_fdio!(status))
45    }
46
47    fn as_handle_ref(&self) -> HandleRef<'_> {
48        self.timer.as_handle_ref()
49    }
50
51    // Not supported.
52    fn get_timeline_change_observer(&self, _: &CurrentTask) -> Option<TimelineChangeObserver> {
53        None
54    }
55}
56
57pub struct BootZxTimer {
58    timer: zx::BootTimer,
59}
60
61impl BootZxTimer {
62    pub fn new() -> Self {
63        Self { timer: zx::BootTimer::create() }
64    }
65}
66
67impl TimerOps for BootZxTimer {
68    fn start(
69        &self,
70        current_task: &CurrentTask,
71        _source: Option<Weak<dyn OnWakeOps>>,
72        deadline: TargetTime,
73    ) -> Result<(), Errno> {
74        let timerslack = current_task.read().get_timerslack();
75        match deadline {
76            TargetTime::BootInstant(t) => {
77                self.timer.set(t, timerslack).map_err(|status| from_status_like_fdio!(status))?
78            }
79            TargetTime::RealTime(t) => {
80                let (boot_instant, _) = estimate_boot_deadline_from_utc(t);
81                self.timer
82                    .set(boot_instant, timerslack)
83                    .map_err(|status| from_status_like_fdio!(status))?
84            }
85            TargetTime::Monotonic(_) => return error!(EINVAL),
86        }
87        Ok(())
88    }
89
90    fn stop(&self, _kernel: &Arc<Kernel>) -> Result<(), Errno> {
91        self.timer.cancel().map_err(|status| from_status_like_fdio!(status))
92    }
93
94    fn as_handle_ref(&self) -> HandleRef<'_> {
95        self.timer.as_handle_ref()
96    }
97
98    // Not supported.
99    fn get_timeline_change_observer(&self, _: &CurrentTask) -> Option<TimelineChangeObserver> {
100        None
101    }
102}