diff --git a/kernel/aster-nix/src/lib.rs b/kernel/aster-nix/src/lib.rs index 8fb1cee0b..dc29a7efd 100644 --- a/kernel/aster-nix/src/lib.rs +++ b/kernel/aster-nix/src/lib.rs @@ -68,6 +68,7 @@ pub mod vm; pub fn init() { driver::init(); + time::init(); net::init(); sched::init(); fs::rootfs::init(boot::initramfs()).unwrap(); diff --git a/kernel/aster-nix/src/time/mod.rs b/kernel/aster-nix/src/time/mod.rs index fa2afeb21..95b2a643e 100644 --- a/kernel/aster-nix/src/time/mod.rs +++ b/kernel/aster-nix/src/time/mod.rs @@ -9,13 +9,17 @@ use crate::prelude::*; mod system_time; -pub use system_time::SystemTime; +pub use system_time::{SystemTime, START_TIME}; pub type clockid_t = i32; pub type time_t = i64; pub type suseconds_t = i64; pub type clock_t = i64; +pub(super) fn init() { + system_time::init_start_time(); +} + #[derive(Debug, Copy, Clone, TryFromInt, PartialEq)] #[repr(i32)] pub enum ClockID { diff --git a/kernel/aster-nix/src/time/system_time.rs b/kernel/aster-nix/src/time/system_time.rs index 9155439a9..bd18fb608 100644 --- a/kernel/aster-nix/src/time/system_time.rs +++ b/kernel/aster-nix/src/time/system_time.rs @@ -3,6 +3,7 @@ use core::time::Duration; use aster_time::{read_monotonic_time, read_start_time}; +use spin::Once; use time::{Date, Month, PrimitiveDateTime, Time}; use crate::prelude::*; @@ -11,6 +12,13 @@ use crate::prelude::*; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct SystemTime(PrimitiveDateTime); +pub static START_TIME: Once = Once::new(); + +pub(super) fn init_start_time() { + let start_time = convert_system_time(read_start_time()).unwrap(); + START_TIME.call_once(|| start_time); +} + impl SystemTime { /// The unix epoch, which represents 1970-01-01 00:00:00 pub const UNIX_EPOCH: SystemTime = SystemTime::unix_epoch(); @@ -29,10 +37,8 @@ impl SystemTime { /// Returns the current system time pub fn now() -> Self { - let start = read_start_time(); - - // The get real time result should always be valid - convert_system_time(start) + START_TIME + .get() .unwrap() .checked_add(read_monotonic_time()) .unwrap() diff --git a/kernel/aster-nix/src/vdso.rs b/kernel/aster-nix/src/vdso.rs index 7f735286d..077c2e593 100644 --- a/kernel/aster-nix/src/vdso.rs +++ b/kernel/aster-nix/src/vdso.rs @@ -12,20 +12,22 @@ //! use. It also hooks up the VDSO data update routine to the time management subsystem for periodic updates. use alloc::{boxed::Box, sync::Arc}; +use core::time::Duration; use aster_frame::{ - sync::Mutex, - vm::{VmIo, PAGE_SIZE}, + sync::SpinLock, + timer::Timer, + vm::{VmFrame, VmIo, PAGE_SIZE}, }; use aster_rights::Rights; -use aster_time::Instant; +use aster_time::{read_monotonic_time, Instant}; use aster_util::coeff::Coeff; use pod::Pod; use spin::Once; use crate::{ fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD}, - time::{ClockID, SystemTime, ALL_SUPPORTED_CLOCK_IDS}, + time::{ClockID, SystemTime, START_TIME}, vm::vmo::{Vmo, VmoOptions}, }; @@ -46,20 +48,25 @@ enum VdsoClockMode { } /// Instant used in `VdsoData`. -/// The `VdsoInstant` records the second of an instant, -/// and the calculation results of multiplying `nanos` with `mult` in the corresponding `VdsoData`. +/// +/// Each `VdsoInstant` will store a instant information for a specified `ClockID`. +/// The `secs` field will record the seconds of the instant, +/// and the `nanos_info` will store the nanoseconds of the instant +/// (for `CLOCK_REALTIME_COARSE` and `CLOCK_MONOTONIC_COARSE`) or +/// the calculation results of left-shift `nanos` with `lshift` +/// (for other high-resolution `ClockID`s). #[repr(C)] #[derive(Debug, Default, Copy, Clone, Pod)] struct VdsoInstant { secs: u64, - nanos_lshift: u64, + nanos_info: u64, } impl VdsoInstant { const fn zero() -> Self { Self { secs: 0, - nanos_lshift: 0, + nanos_info: 0, } } } @@ -70,7 +77,7 @@ struct ArchVdsoData {} /// A POD (Plain Old Data) structure maintaining timing information that required for userspace. /// -/// Since currently we directly use the vdso shared library of Linux, +/// Since currently we directly use the VDSO shared library of Linux, /// currently it aligns with the Linux VDSO shared library format and contents /// (Linux v6.2.10) #[repr(C)] @@ -93,6 +100,18 @@ struct VdsoData { arch_data: ArchVdsoData, } +const HIGH_RES_CLOCK_IDS: [ClockID; 4] = [ + ClockID::CLOCK_REALTIME, + ClockID::CLOCK_MONOTONIC, + ClockID::CLOCK_MONOTONIC_RAW, + ClockID::CLOCK_BOOTTIME, +]; + +const COARSE_RES_CLOCK_IDS: [ClockID; 2] = [ + ClockID::CLOCK_REALTIME_COARSE, + ClockID::CLOCK_MONOTONIC_COARSE, +]; + impl VdsoData { const fn empty() -> Self { VdsoData { @@ -111,13 +130,16 @@ impl VdsoData { } } - /// Init vdso data based on the default clocksource. + /// Init VDSO data based on the default clocksource. fn init(&mut self) { let clocksource = aster_time::default_clocksource(); let coeff = clocksource.coeff(); self.set_clock_mode(DEFAULT_CLOCK_MODE); self.set_coeff(coeff); - self.update_instant(clocksource.last_instant(), clocksource.last_cycles()); + + let (last_instant, last_cycles) = clocksource.last_record(); + self.update_high_res_instant(last_instant, last_cycles); + self.update_coarse_res_instant(last_instant); } fn set_clock_mode(&mut self, mode: VdsoClockMode) { @@ -129,21 +151,20 @@ impl VdsoData { self.shift = coeff.shift(); } - fn update_clock_instant(&mut self, clockid: usize, secs: u64, nanos_lshift: u64) { + fn update_clock_instant(&mut self, clockid: usize, secs: u64, nanos_info: u64) { self.basetime[clockid].secs = secs; - self.basetime[clockid].nanos_lshift = nanos_lshift; + self.basetime[clockid].nanos_info = nanos_info; } - fn update_instant(&mut self, instant: Instant, instant_cycles: u64) { + fn update_high_res_instant(&mut self, instant: Instant, instant_cycles: u64) { self.last_cycles = instant_cycles; - const REALTIME_IDS: [ClockID; 2] = - [ClockID::CLOCK_REALTIME, ClockID::CLOCK_REALTIME_COARSE]; - for clock_id in ALL_SUPPORTED_CLOCK_IDS { - let secs = if REALTIME_IDS.contains(&clock_id) { + for clock_id in HIGH_RES_CLOCK_IDS { + let secs = if clock_id == ClockID::CLOCK_REALTIME { instant.secs() + START_SECS_COUNT.get().unwrap() } else { instant.secs() }; + self.update_clock_instant( clock_id as usize, secs, @@ -151,31 +172,48 @@ impl VdsoData { ); } } + + fn update_coarse_res_instant(&mut self, instant: Instant) { + for clock_id in COARSE_RES_CLOCK_IDS { + let secs = if clock_id == ClockID::CLOCK_REALTIME_COARSE { + instant.secs() + START_SECS_COUNT.get().unwrap() + } else { + instant.secs() + }; + self.update_clock_instant(clock_id as usize, secs, instant.nanos() as u64); + } + } } /// Vdso (virtual dynamic shared object) is used to export some safe kernel space routines to user space applications /// so that applications can call these kernel space routines in-process, without context switching. /// -/// Vdso maintains a `VdsoData` instance that contains data information required for vdso mechanism, -/// and a `Vmo` that contains all vdso-related information, including the vdso data and the vdso calling interfaces. +/// Vdso maintains a `VdsoData` instance that contains data information required for VDSO mechanism, +/// and a `Vmo` that contains all VDSO-related information, including the VDSO data and the VDSO calling interfaces. /// This `Vmo` must be mapped to every userspace process. struct Vdso { /// A VdsoData instance. - data: Mutex, - /// the vmo of the entire vdso, including the library text and the vdso data. + data: SpinLock, + /// The vmo of the entire VDSO, including the library text and the VDSO data. vmo: Arc, + /// The `VmFrame` that contains the VDSO data. This frame is contained in and + /// will not be removed from the VDSO vmo. + data_frame: VmFrame, } +/// A `SpinLock` for the `seq` field in `VdsoData`. +static SEQ_LOCK: SpinLock<()> = SpinLock::new(()); + impl Vdso { - /// Construct a new Vdso, including an initialized `VdsoData` and a vmo of the vdso. + /// Construct a new Vdso, including an initialized `VdsoData` and a vmo of the VDSO. fn new() -> Self { let mut vdso_data = VdsoData::empty(); vdso_data.init(); - let vdso_vmo = { + let (vdso_vmo, data_frame) = { let vmo_options = VmoOptions::::new(5 * PAGE_SIZE); let vdso_vmo = vmo_options.alloc().unwrap(); - // Write vdso data to vdso vmo. + // Write VDSO data to VDSO vmo. vdso_vmo.write_bytes(0x80, vdso_data.as_bytes()).unwrap(); let vdso_lib_vmo = { @@ -186,62 +224,87 @@ impl Vdso { }; let mut vdso_text = Box::new([0u8; PAGE_SIZE]); vdso_lib_vmo.read_bytes(0, &mut *vdso_text).unwrap(); - // Write vdso library to vdso vmo. + // Write VDSO library to VDSO vmo. vdso_vmo.write_bytes(0x4000, &*vdso_text).unwrap(); - vdso_vmo + let data_frame = vdso_vmo.get_committed_frame(0, true).unwrap(); + (vdso_vmo, data_frame) }; Self { - data: Mutex::new(vdso_data), + data: SpinLock::new(vdso_data), vmo: Arc::new(vdso_vmo), + data_frame, } } - /// Return the vdso vmo. - fn vmo(&self) -> Arc { - self.vmo.clone() - } - - fn update_instant(&self, instant: Instant, instant_cycles: u64) { - self.data.lock().update_instant(instant, instant_cycles); + fn update_high_res_instant(&self, instant: Instant, instant_cycles: u64) { + let seq_lock = SEQ_LOCK.lock(); + self.data + .lock() + .update_high_res_instant(instant, instant_cycles); // Update begins. - self.vmo.write_val(0x80, &1).unwrap(); - self.vmo.write_val(0x88, &instant_cycles).unwrap(); - for clock_id in ALL_SUPPORTED_CLOCK_IDS { - self.update_vmo_instant(clock_id); + self.data_frame.write_val(0x80, &1).unwrap(); + self.data_frame.write_val(0x88, &instant_cycles).unwrap(); + for clock_id in HIGH_RES_CLOCK_IDS { + self.update_data_frame_instant(clock_id); } + // Update finishes. - self.vmo.write_val(0x80, &0).unwrap(); + self.data_frame.write_val(0x80, &0).unwrap(); } - /// Update the requisite fields of the vdso data in the vmo. - fn update_vmo_instant(&self, clockid: ClockID) { + fn update_coarse_res_instant(&self, instant: Instant) { + let seq_lock = SEQ_LOCK.lock(); + self.data.lock().update_coarse_res_instant(instant); + + // Update begins. + self.data_frame.write_val(0x80, &1).unwrap(); + for clock_id in COARSE_RES_CLOCK_IDS { + self.update_data_frame_instant(clock_id); + } + + // Update finishes. + self.data_frame.write_val(0x80, &0).unwrap(); + } + + /// Update the requisite fields of the VDSO data in the `data_frame`. + fn update_data_frame_instant(&self, clockid: ClockID) { let clock_index = clockid as usize; let secs_offset = 0xA0 + clock_index * 0x10; - let nanos_lshift_offset = 0xA8 + clock_index * 0x10; + let nanos_info_offset = 0xA8 + clock_index * 0x10; let data = self.data.lock(); - self.vmo + self.data_frame .write_val(secs_offset, &data.basetime[clock_index].secs) .unwrap(); - self.vmo - .write_val( - nanos_lshift_offset, - &data.basetime[clock_index].nanos_lshift, - ) + self.data_frame + .write_val(nanos_info_offset, &data.basetime[clock_index].nanos_info) .unwrap(); } } -/// Update the `VdsoInstant` in Vdso. -fn update_vdso_instant(instant: Instant, instant_cycles: u64) { - VDSO.get().unwrap().update_instant(instant, instant_cycles); +/// Update the `VdsoInstant` for clock IDs with high resolution in Vdso. +fn update_vdso_high_res_instant(instant: Instant, instant_cycles: u64) { + VDSO.get() + .unwrap() + .update_high_res_instant(instant, instant_cycles); +} + +/// Update the `VdsoInstant` for clock IDs with coarse resolution in Vdso. +fn update_vdso_coarse_res_instant(timer: Arc) { + let instant = Instant::from(read_monotonic_time()); + VDSO.get().unwrap().update_coarse_res_instant(instant); + + timer.set(Duration::from_millis(100)); } /// Init `START_SECS_COUNT`, which is used to record the seconds passed since 1970-01-01 00:00:00. fn init_start_secs_count() { - let now = SystemTime::now(); - let time_duration = now.duration_since(&SystemTime::UNIX_EPOCH).unwrap(); + let time_duration = START_TIME + .get() + .unwrap() + .duration_since(&SystemTime::UNIX_EPOCH) + .unwrap(); START_SECS_COUNT.call_once(|| time_duration.as_secs()); } @@ -250,15 +313,20 @@ fn init_vdso() { VDSO.call_once(|| Arc::new(vdso)); } -/// Init vdso module. +/// Init this module. pub(super) fn init() { init_start_secs_count(); init_vdso(); - aster_time::VDSO_DATA_UPDATE.call_once(|| Arc::new(update_vdso_instant)); + aster_time::VDSO_DATA_HIGH_RES_UPDATE_FN.call_once(|| Arc::new(update_vdso_high_res_instant)); + + // Coarse resolution clock IDs directly read the instant stored in VDSO data without + // using coefficients for calculation, thus the related instant requires more frequent updating. + let coarse_instant_timer = Timer::new(update_vdso_coarse_res_instant).unwrap(); + coarse_instant_timer.set(Duration::from_millis(100)); } -/// Return the vdso vmo. +/// Return the VDSO vmo. pub(crate) fn vdso_vmo() -> Option> { - // We allow that vdso does not exist - VDSO.get().map(|vdso| vdso.vmo()) + // We allow that VDSO does not exist + VDSO.get().map(|vdso| vdso.vmo.clone()) } diff --git a/kernel/comps/time/src/clocksource.rs b/kernel/comps/time/src/clocksource.rs index bcf36e0e8..563ca9e55 100644 --- a/kernel/comps/time/src/clocksource.rs +++ b/kernel/comps/time/src/clocksource.rs @@ -1,16 +1,19 @@ // SPDX-License-Identifier: MPL-2.0 -//! This module provides abstractions for hardware-assisted timing mechanisms, encapsulated by the `ClockSource` struct. -//! A `ClockSource` can be constructed from any counter with a stable frequency, enabling precise time measurements to be taken -//! by retrieving instances of `Instant`. +//! This module provides abstractions for hardware-assisted timing mechanisms, encapsulated +//! by the `ClockSource` struct. //! -//! The `ClockSource` module is a fundamental building block for timing in systems that require high precision and accuracy. -//! It can be integrated into larger systems to provide timing capabilities, or used standalone for time tracking and elapsed time measurements. +//! A `ClockSource` can be constructed from any counter with a stable frequency, enabling precise +//! time measurements to be taken by retrieving instances of `Instant`. +//! +//! The `ClockSource` module is a fundamental building block for timing in systems that require +//! high precision and accuracy. It can be integrated into larger systems to provide timing capabilities, +//! or used standalone for time tracking and elapsed time measurements. use alloc::sync::Arc; use core::{cmp::max, ops::Add, time::Duration}; -use aster_frame::sync::SpinLock; +use aster_frame::sync::RwLock; use aster_util::coeff::Coeff; use crate::NANOS_PER_SECOND; @@ -20,15 +23,21 @@ use crate::NANOS_PER_SECOND; /// Users are able to measure time by retrieving `Instant` from this source. /// /// # Implementation -/// The `ClockSource` relies on obtaining the frequency of the counter and the method for reading the cycles in order to measure time. +/// The `ClockSource` relies on obtaining the frequency of the counter and the method for +/// reading the cycles in order to measure time. +/// /// The **cycles** here refer the counts of the base time counter. -/// Additionally, the `ClockSource` also holds a last recorded instant, which acts as a reference point for subsequent time retrieval. -/// To prevent numerical overflow during the calculation of `Instant`, this last recorded instant **must be periodically refreshed**. -/// The maximum interval for these updates must be determined at the time of the `ClockSource` initialization. +/// +/// Additionally, the `ClockSource` also holds a last record for an `Instant` and the +/// corresponding cycles, which acts as a reference point for subsequent time retrieval. +/// To prevent numerical overflow during the calculation of `Instant`, this last recorded instant +/// **must be periodically refreshed**. The maximum interval for these updates must be determined +/// at the time of the `ClockSource` initialization. /// /// # Examples -/// Suppose we have a counter called `counter` which have the frequency `counter.freq`, and the method to read its cycles called `read_counter()`. -/// We can create a corresponding `ClockSource` and use it as follows: +/// Suppose we have a counter called `counter` which have the frequency `counter.freq`, and the method +/// to read its cycles called `read_counter()`. We can create a corresponding `ClockSource` and +/// use it as follows: /// /// ```rust /// // here we set the max_delay_secs = 10 @@ -45,16 +54,17 @@ pub struct ClockSource { read_cycles: Arc u64 + Sync + Send>, base: ClockSourceBase, coeff: Coeff, - last_instant: SpinLock, - last_cycles: SpinLock, + /// A record to an `Instant` and the corresponding cycles of this `ClockSource`. + last_record: RwLock<(Instant, u64)>, } impl ClockSource { /// Create a new `ClockSource` instance. - /// Require basic information of based time counter, including the function for reading cycles, the frequency - /// and the maximum delay seconds to update this `ClockSource`. - /// The `ClockSource` also calculates a reliable `Coeff` based on the counter's frequency and the maximum delay seconds. - /// This `Coeff` is used to convert the number of cycles into the duration of time that has passed for those cycles. + /// Require basic information of based time counter, including the function for reading cycles, + /// the frequency and the maximum delay seconds to update this `ClockSource`. + /// The `ClockSource` also calculates a reliable `Coeff` based on the counter's frequency and + /// the maximum delay seconds. This `Coeff` is used to convert the number of cycles into + /// the duration of time that has passed for those cycles. pub fn new( freq: u64, max_delay_secs: u64, @@ -68,8 +78,7 @@ impl ClockSource { read_cycles, base, coeff, - last_instant: SpinLock::new(Instant::zero()), - last_cycles: SpinLock::new(0), + last_record: RwLock::new((Instant::zero(), 0)), } } @@ -78,25 +87,23 @@ impl ClockSource { } /// Use the instant cycles to calculate the instant. - /// It first calculates the difference between the instant cycles and the last recorded cycles stored in the clocksource. - /// Then `ClockSource` will convert the passed cycles into passed time and calculate the current instant. + /// + /// It first calculates the difference between the instant cycles and the last + /// recorded cycles stored in the clocksource. Then `ClockSource` will convert + /// the passed cycles into passed time and calculate the current instant. fn calculate_instant(&self, instant_cycles: u64) -> Instant { + let (last_instant, last_cycles) = *self.last_record.read_irq_disabled(); let delta_nanos = { - let delta_cycles = instant_cycles - self.last_cycles(); + let delta_cycles = instant_cycles - last_cycles; self.cycles_to_nanos(delta_cycles) }; let duration = Duration::from_nanos(delta_nanos); - self.last_instant() + duration + last_instant + duration } - /// Use an input instant to update the internal instant in the `ClockSource`. - fn update_last_instant(&self, instant: &Instant) { - *self.last_instant.lock() = *instant; - } - - /// Use an input cycles to update the internal instant in the `ClockSource`. - fn update_last_cycles(&self, cycles: u64) { - *self.last_cycles.lock() = cycles; + /// Use an input instant and cycles to update the `last_record` in the `ClockSource`. + fn update_last_record(&self, record: (Instant, u64)) { + *self.last_record.write_irq_disabled() = record; } /// read current cycles of the `ClockSource`. @@ -104,19 +111,14 @@ impl ClockSource { (self.read_cycles)() } - /// Return the last instant recorded in the `ClockSource`. - pub fn last_instant(&self) -> Instant { - return *self.last_instant.lock(); - } - - /// Return the last cycles recorded in the `ClockSource`. - pub fn last_cycles(&self) -> u64 { - return *self.last_cycles.lock(); + /// Return the last instant and last cycles recorded in the `ClockSource`. + pub fn last_record(&self) -> (Instant, u64) { + return *self.last_record.read_irq_disabled(); } /// Return the maximum delay seconds for updating of the `ClockSource`. pub fn max_delay_secs(&self) -> u64 { - self.base.max_delay_secs() + self.base.max_delay_secs } /// Return the reference to the generated cycles coeff of the `ClockSource`. @@ -126,26 +128,24 @@ impl ClockSource { /// Return the frequency of the counter used in the `ClockSource`. pub fn freq(&self) -> u64 { - self.base.freq() + self.base.freq } /// Calibrate the recorded `Instant` to zero, and record the instant cycles. pub(crate) fn calibrate(&self, instant_cycles: u64) { - self.update_last_cycles(instant_cycles); - self.update_last_instant(&Instant::zero()); + self.update_last_record((Instant::zero(), instant_cycles)); } /// Get the instant to update the internal instant in the `ClockSource`. pub(crate) fn update(&self) { let instant_cycles = self.read_cycles(); let instant = self.calculate_instant(instant_cycles); - self.update_last_cycles(instant_cycles); - self.update_last_instant(&instant); + self.update_last_record((instant, instant_cycles)); } /// Read the instant corresponding to the current time. - /// When trying to read an instant from the clocksource, it will use the reading method to read instant cycles. - /// Then leverage it to calculate the instant. + /// When trying to read an instant from the clocksource, it will use the reading method + /// to read instant cycles. Then leverage it to calculate the instant. pub(crate) fn read_instant(&self) -> Instant { let instant_cycles = self.read_cycles(); self.calculate_instant(instant_cycles) @@ -162,10 +162,12 @@ pub struct Instant { } impl Instant { + /// Create a zeroed `Instant`. pub const fn zero() -> Self { Self { secs: 0, nanos: 0 } } + /// Create an new `Instant` based on the inputting `secs` and `nanos`. pub fn new(secs: u64, nanos: u32) -> Self { Self { secs, nanos } } @@ -181,6 +183,15 @@ impl Instant { } } +impl From for Instant { + fn from(value: Duration) -> Self { + Self { + secs: value.as_secs(), + nanos: value.subsec_nanos(), + } + } +} + impl Add for Instant { type Output = Instant; @@ -210,12 +221,4 @@ impl ClockSourceBase { max_delay_secs, } } - - fn max_delay_secs(&self) -> u64 { - self.max_delay_secs - } - - fn freq(&self) -> u64 { - self.freq - } } diff --git a/kernel/comps/time/src/lib.rs b/kernel/comps/time/src/lib.rs index b1a426975..cc00d4b8a 100644 --- a/kernel/comps/time/src/lib.rs +++ b/kernel/comps/time/src/lib.rs @@ -21,7 +21,8 @@ mod rtc; mod tsc; pub const NANOS_PER_SECOND: u32 = 1_000_000_000; -pub static VDSO_DATA_UPDATE: Once> = Once::new(); +pub static VDSO_DATA_HIGH_RES_UPDATE_FN: Once> = + Once::new(); #[init_component] fn time_init() -> Result<(), ComponentInitError> { diff --git a/kernel/comps/time/src/tsc.rs b/kernel/comps/time/src/tsc.rs index a2e0bd4e2..d460fe869 100644 --- a/kernel/comps/time/src/tsc.rs +++ b/kernel/comps/time/src/tsc.rs @@ -14,7 +14,7 @@ use spin::Once; use crate::{ clocksource::{ClockSource, Instant}, - START_TIME, VDSO_DATA_UPDATE, + START_TIME, VDSO_DATA_HIGH_RES_UPDATE_FN, }; /// A instance of TSC clocksource. @@ -58,8 +58,9 @@ fn update_clocksource(timer: Arc) { clock.update(); // Update vdso data. - if VDSO_DATA_UPDATE.is_completed() { - VDSO_DATA_UPDATE.get().unwrap()(clock.last_instant(), clock.last_cycles()); + if let Some(update_fn) = VDSO_DATA_HIGH_RES_UPDATE_FN.get() { + let (last_instant, last_cycles) = clock.last_record(); + update_fn(last_instant, last_cycles); } // Setting the timer as `clock.max_delay_secs() - 1` is to avoid // the actual delay time is greater than the maximum delay seconds due to the latency of execution.