Simplify the code in `aster-time`
This commit is contained in:
parent
bbe0e3f3bb
commit
9a8e6fd372
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue