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