1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! A helper binary for reading CLOCK_BOOTTIME and CLOCK_MONOTONIC
//! to verify the virtio-pvclock behavior.
//! This program is used by corresponding e2e_tests.

use std::time::Duration;

use serde::Deserialize;
use serde::Serialize;

#[cfg(any(target_os = "linux", target_os = "android"))]
fn clock_gettime_nanos(clock_id: i32) -> u64 {
    let mut ts = libc::timespec {
        tv_sec: 0,
        tv_nsec: 0,
    };
    // SAFETY: This is safe since clock_gettime will succeed always
    // and will not break Rust's assumption on data structures
    // because it is called with valid parameters.
    assert_eq!(unsafe { libc::clock_gettime(clock_id, &mut ts) }, 0);
    ts.tv_sec as u64 * 1_000_000_000u64 + ts.tv_nsec as u64
}

#[cfg(any(target_os = "linux", target_os = "android"))]
fn clock_monotonic_now() -> Duration {
    Duration::from_nanos(clock_gettime_nanos(libc::CLOCK_MONOTONIC))
}

#[cfg(any(target_os = "linux", target_os = "android"))]
fn clock_boottime_now() -> Duration {
    Duration::from_nanos(clock_gettime_nanos(libc::CLOCK_BOOTTIME))
}

/// ClockValues hold the values read out from the kernel
/// via clock_gettime syscall.
#[derive(Serialize, Deserialize, Debug)]
pub struct ClockValues {
    pub clock_monotonic: Duration,
    pub clock_boottime: Duration,
}
impl ClockValues {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub fn now() -> Self {
        Self {
            clock_monotonic: clock_monotonic_now(),
            clock_boottime: clock_boottime_now(),
        }
    }
    pub fn clock_monotonic(&self) -> Duration {
        self.clock_monotonic
    }
    pub fn clock_boottime(&self) -> Duration {
        self.clock_boottime
    }
}