Skip to main content

aperture_shared/utils/
time.rs

1//! Time-related utilities
2
3use std::time::{SystemTime, UNIX_EPOCH};
4
5/// Get the current system time in nanoseconds since UNIX epoch
6pub fn system_time_nanos() -> u64 {
7    SystemTime::now()
8        .duration_since(UNIX_EPOCH)
9        .expect("system time before UNIX epoch")
10        .as_nanos() as u64
11}
12
13/// Get the current system time in seconds since UNIX epoch
14pub fn system_time_secs() -> u64 {
15    SystemTime::now()
16        .duration_since(UNIX_EPOCH)
17        .expect("system time before UNIX epoch")
18        .as_secs()
19}
20
21/// Compute the offset between CLOCK_MONOTONIC and CLOCK_REALTIME.
22///
23/// `bpf_ktime_get_ns()` returns CLOCK_MONOTONIC nanoseconds.
24/// Adding this offset converts to wall-clock (UNIX epoch) nanoseconds.
25#[cfg(target_os = "linux")]
26fn boot_time_offset_ns() -> u64 {
27    let mut mono = libc::timespec {
28        tv_sec: 0,
29        tv_nsec: 0,
30    };
31    let mut real = libc::timespec {
32        tv_sec: 0,
33        tv_nsec: 0,
34    };
35
36    // SAFETY: passing valid pointers to clock_gettime
37    unsafe {
38        libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut mono);
39        libc::clock_gettime(libc::CLOCK_REALTIME, &mut real);
40    }
41
42    let mono_ns = mono.tv_sec as u64 * 1_000_000_000 + mono.tv_nsec as u64;
43    let real_ns = real.tv_sec as u64 * 1_000_000_000 + real.tv_nsec as u64;
44
45    real_ns.saturating_sub(mono_ns)
46}
47
48/// Convert boot time (from eBPF `bpf_ktime_get_ns()`) to system time
49/// (nanoseconds since UNIX epoch).
50#[cfg(target_os = "linux")]
51pub fn boot_time_to_system_time(boot_time_ns: u64) -> u64 {
52    boot_time_ns + boot_time_offset_ns()
53}
54
55/// Fallback for non-Linux: return the value unchanged.
56#[cfg(not(target_os = "linux"))]
57pub fn boot_time_to_system_time(boot_time_ns: u64) -> u64 {
58    boot_time_ns
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_system_time() {
67        let nanos = system_time_nanos();
68        let secs = system_time_secs();
69
70        // Basic sanity check
71        assert!(nanos > 0);
72        assert!(secs > 1_600_000_000); // After 2020
73    }
74}