Simplify the code in `aster-time`

This commit is contained in:
Ruihan Li 2025-10-29 22:17:00 +08:00 committed by Tate, Hongliang Tian
parent bbe0e3f3bb
commit 9a8e6fd372
4 changed files with 24 additions and 55 deletions

View File

@ -16,9 +16,10 @@ use core::{cmp::max, ops::Add, time::Duration};
use aster_util::coeff::Coeff;
use ostd::sync::{LocalIrqDisabled, RwLock};
use crate::NANOS_PER_SECOND;
const NANOS_PER_SECOND: u32 = 1_000_000_000;
/// `ClockSource` is an abstraction for hardware-assisted timing mechanisms.
///
/// A `ClockSource` can be created based on any counter that operates at a stable frequency.
/// Users are able to measure time by retrieving `Instant` from this source.
///
@ -60,8 +61,9 @@ pub struct ClockSource {
impl ClockSource {
/// Creates 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`.
///
/// This method requires basic information of the 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.
@ -71,7 +73,7 @@ impl ClockSource {
read_cycles: Arc<dyn Fn() -> u64 + Sync + Send>,
) -> Self {
let base = ClockSourceBase::new(freq, max_delay_secs);
// Too big `max_delay_secs` will lead to a low resolution Coeff.
// Too big `max_delay_secs` will lead to a low resolution `Coeff`.
debug_assert!(max_delay_secs < 600);
let coeff = Coeff::new(NANOS_PER_SECOND as u64, freq, max_delay_secs * freq);
Self {

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! The system time of Asterinas.
#![feature(let_chains)]
#![no_std]
#![deny(unsafe_code)]
@ -10,10 +11,8 @@ extern crate alloc;
use alloc::sync::Arc;
use core::time::Duration;
use clocksource::ClockSource;
pub use clocksource::Instant;
pub use clocksource::{ClockSource, Instant};
use component::{init_component, ComponentInitError};
use ostd::sync::Mutex;
use rtc::Driver;
use spin::Once;
@ -21,9 +20,8 @@ mod clocksource;
mod rtc;
mod tsc;
pub const NANOS_PER_SECOND: u32 = 1_000_000_000;
pub static VDSO_DATA_HIGH_RES_UPDATE_FN: Once<Arc<dyn Fn(Instant, u64) + Sync + Send>> =
Once::new();
pub static VDSO_DATA_HIGH_RES_UPDATE_FN: Once<fn(Instant, u64)> = Once::new();
static RTC_DRIVER: Once<Arc<dyn Driver + Send + Sync>> = Once::new();
#[init_component]
@ -45,50 +43,20 @@ pub struct SystemTime {
pub nanos: u64,
}
impl SystemTime {
pub(crate) const fn zero() -> Self {
Self {
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
nanos: 0,
}
}
}
static START_TIME: Once<SystemTime> = Once::new();
pub(crate) static READ_TIME: Mutex<SystemTime> = Mutex::new(SystemTime::zero());
pub(crate) static START_TIME: Once<SystemTime> = Once::new();
/// get real time
pub fn get_real_time() -> SystemTime {
read()
}
pub fn read() -> SystemTime {
update_time();
*READ_TIME.lock()
}
fn update_time() {
let mut lock = READ_TIME.lock();
*lock = RTC_DRIVER.get().unwrap().read_rtc();
}
/// Return the `START_TIME`, which is the actual time when doing calibrate.
/// Returns the `START_TIME`, which is the system time when calibrating.
pub fn read_start_time() -> SystemTime {
*START_TIME.get().unwrap()
}
/// Return the monotonic time from the tsc clocksource.
/// Returns the monotonic time from the TSC clocksource.
pub fn read_monotonic_time() -> Duration {
let instant = tsc::read_instant();
Duration::new(instant.secs(), instant.nanos())
}
/// Return the tsc clocksource.
/// Returns the default (TSC) clocksource.
pub fn default_clocksource() -> Arc<ClockSource> {
tsc::CLOCK.get().unwrap().clone()
}

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! This module provide a instance of `ClockSource` based on TSC.
//!
//! Use `init` to initialize this module.
use alloc::sync::Arc;
use core::sync::atomic::{AtomicU64, Ordering};
@ -17,12 +16,12 @@ use crate::{
START_TIME, VDSO_DATA_HIGH_RES_UPDATE_FN,
};
/// A instance of TSC clocksource.
pub static CLOCK: Once<Arc<ClockSource>> = Once::new();
/// An instance of the TSC clocksource.
pub(super) static CLOCK: Once<Arc<ClockSource>> = Once::new();
const MAX_DELAY_SECS: u64 = 100;
/// Init tsc clocksource module.
/// Initializes the TSC clocksource module.
pub(super) fn init() {
init_clock();
calibrate();
@ -39,15 +38,15 @@ fn init_clock() {
});
}
/// Calibrate the TSC and system time based on the RTC time.
/// Calibrates the TSC and system time based on the RTC time.
fn calibrate() {
let clock = CLOCK.get().unwrap();
let cycles = clock.read_cycles();
clock.calibrate(cycles);
START_TIME.call_once(crate::read);
START_TIME.call_once(|| crate::RTC_DRIVER.get().unwrap().read_rtc());
}
/// Read an `Instant` of tsc clocksource.
/// Reads an `Instant` of the TSC clocksource.
pub(super) fn read_instant() -> Instant {
let clock = CLOCK.get().unwrap();
clock.read_instant()
@ -57,7 +56,7 @@ fn update_clocksource() {
let clock = CLOCK.get().unwrap();
clock.update();
// Update vdso data.
// Update vDSO data.
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);
@ -84,6 +83,6 @@ fn init_timer() {
}
};
// TODO: re-organize the code structure and use the `Timer` to achieve the updating.
// TODO: Re-organize the code structure and use the `Timer` to achieve the updating.
timer::register_callback_on_cpu(update);
}

View File

@ -361,7 +361,7 @@ pub(super) fn init_in_first_kthread() {
init_start_secs_count();
init_vdso();
aster_time::VDSO_DATA_HIGH_RES_UPDATE_FN.call_once(|| Arc::new(update_vdso_high_res_instant));
aster_time::VDSO_DATA_HIGH_RES_UPDATE_FN.call_once(|| 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.