readclock/
lib.rs

1// Copyright 2024 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! A helper binary for reading CLOCK_BOOTTIME and CLOCK_MONOTONIC
6//! to verify the virtio-pvclock behavior.
7//! This program is used by corresponding e2e_tests.
8
9use std::time::Duration;
10
11use serde::Deserialize;
12use serde::Serialize;
13
14#[cfg(any(target_os = "linux", target_os = "android"))]
15fn clock_gettime_nanos(clock_id: i32) -> u64 {
16    let mut ts = libc::timespec {
17        tv_sec: 0,
18        tv_nsec: 0,
19    };
20    // SAFETY: This is safe since clock_gettime will succeed always
21    // and will not break Rust's assumption on data structures
22    // because it is called with valid parameters.
23    assert_eq!(unsafe { libc::clock_gettime(clock_id, &mut ts) }, 0);
24    ts.tv_sec as u64 * 1_000_000_000u64 + ts.tv_nsec as u64
25}
26
27#[cfg(any(target_os = "linux", target_os = "android"))]
28fn clock_monotonic_now() -> Duration {
29    Duration::from_nanos(clock_gettime_nanos(libc::CLOCK_MONOTONIC))
30}
31
32#[cfg(any(target_os = "linux", target_os = "android"))]
33fn clock_boottime_now() -> Duration {
34    Duration::from_nanos(clock_gettime_nanos(libc::CLOCK_BOOTTIME))
35}
36
37/// ClockValues hold the values read out from the kernel
38/// via clock_gettime syscall.
39#[derive(Serialize, Deserialize, Debug)]
40pub struct ClockValues {
41    pub clock_monotonic: Duration,
42    pub clock_boottime: Duration,
43}
44impl ClockValues {
45    #[cfg(any(target_os = "linux", target_os = "android"))]
46    pub fn now() -> Self {
47        Self {
48            clock_monotonic: clock_monotonic_now(),
49            clock_boottime: clock_boottime_now(),
50        }
51    }
52    pub fn clock_monotonic(&self) -> Duration {
53        self.clock_monotonic
54    }
55    pub fn clock_boottime(&self) -> Duration {
56        self.clock_boottime
57    }
58}