mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-12 23:06:51 +00:00
Fix a concurrency bug in clocksource
This commit is contained in:
parent
0291b5dc6b
commit
364ef48e2f
@ -59,7 +59,7 @@ pub struct ClockSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ClockSource {
|
impl ClockSource {
|
||||||
/// Create a new `ClockSource` instance.
|
/// Creates a new `ClockSource` instance.
|
||||||
/// Require basic information of based time counter, including the function for reading 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 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 `ClockSource` also calculates a reliable `Coeff` based on the counter's frequency and
|
||||||
@ -86,69 +86,72 @@ impl ClockSource {
|
|||||||
self.coeff * cycles
|
self.coeff * cycles
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use the instant cycles to calculate the instant.
|
/// Uses the instant cycles to calculate the instant.
|
||||||
///
|
///
|
||||||
/// It first calculates the difference between the instant cycles and the last
|
/// It first calculates the difference between the instant cycles and the last
|
||||||
/// recorded cycles stored in the clocksource. Then `ClockSource` will convert
|
/// recorded cycles stored in the clocksource. Then `ClockSource` will convert
|
||||||
/// the passed cycles into passed time and calculate the current instant.
|
/// 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();
|
/// Returns the calculated instant and instant cycles.
|
||||||
|
fn calculate_instant(&self) -> (Instant, u64) {
|
||||||
|
let (instant_cycles, last_instant, last_cycles) = {
|
||||||
|
let last_record = self.last_record.read_irq_disabled();
|
||||||
|
let (last_instant, last_cycles) = *last_record;
|
||||||
|
(self.read_cycles(), last_instant, last_cycles)
|
||||||
|
};
|
||||||
|
|
||||||
let delta_nanos = {
|
let delta_nanos = {
|
||||||
let delta_cycles = instant_cycles - last_cycles;
|
let delta_cycles = instant_cycles - last_cycles;
|
||||||
self.cycles_to_nanos(delta_cycles)
|
self.cycles_to_nanos(delta_cycles)
|
||||||
};
|
};
|
||||||
let duration = Duration::from_nanos(delta_nanos);
|
let duration = Duration::from_nanos(delta_nanos);
|
||||||
last_instant + duration
|
(last_instant + duration, instant_cycles)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use an input instant and cycles to update the `last_record` in the `ClockSource`.
|
/// Uses an input instant and cycles to update the `last_record` in the `ClockSource`.
|
||||||
fn update_last_record(&self, record: (Instant, u64)) {
|
fn update_last_record(&self, record: (Instant, u64)) {
|
||||||
*self.last_record.write_irq_disabled() = record;
|
*self.last_record.write_irq_disabled() = record;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// read current cycles of the `ClockSource`.
|
/// Reads current cycles of the `ClockSource`.
|
||||||
pub fn read_cycles(&self) -> u64 {
|
pub fn read_cycles(&self) -> u64 {
|
||||||
(self.read_cycles)()
|
(self.read_cycles)()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the last instant and last cycles recorded in the `ClockSource`.
|
/// Returns the last instant and last cycles recorded in the `ClockSource`.
|
||||||
pub fn last_record(&self) -> (Instant, u64) {
|
pub fn last_record(&self) -> (Instant, u64) {
|
||||||
return *self.last_record.read_irq_disabled();
|
return *self.last_record.read_irq_disabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the maximum delay seconds for updating of the `ClockSource`.
|
/// Returns the maximum delay seconds for updating of the `ClockSource`.
|
||||||
pub fn max_delay_secs(&self) -> u64 {
|
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`.
|
/// Returns the reference to the generated cycles coeff of the `ClockSource`.
|
||||||
pub fn coeff(&self) -> &Coeff {
|
pub fn coeff(&self) -> &Coeff {
|
||||||
&self.coeff
|
&self.coeff
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the frequency of the counter used in the `ClockSource`.
|
/// Returns the frequency of the counter used in the `ClockSource`.
|
||||||
pub fn freq(&self) -> u64 {
|
pub fn freq(&self) -> u64 {
|
||||||
self.base.freq
|
self.base.freq
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calibrate the recorded `Instant` to zero, and record the instant cycles.
|
/// Calibrates the recorded `Instant` to zero, and record the instant cycles.
|
||||||
pub(crate) fn calibrate(&self, instant_cycles: u64) {
|
pub(crate) fn calibrate(&self, instant_cycles: u64) {
|
||||||
self.update_last_record((Instant::zero(), instant_cycles));
|
self.update_last_record((Instant::zero(), instant_cycles));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the instant to update the internal instant in the `ClockSource`.
|
/// Gets the instant to update the internal instant in the `ClockSource`.
|
||||||
pub(crate) fn update(&self) {
|
pub(crate) fn update(&self) {
|
||||||
let instant_cycles = self.read_cycles();
|
let (instant, instant_cycles) = self.calculate_instant();
|
||||||
let instant = self.calculate_instant(instant_cycles);
|
|
||||||
self.update_last_record((instant, instant_cycles));
|
self.update_last_record((instant, instant_cycles));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the instant corresponding to the current time.
|
/// Reads 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.
|
|
||||||
pub(crate) fn read_instant(&self) -> Instant {
|
pub(crate) fn read_instant(&self) -> Instant {
|
||||||
let instant_cycles = self.read_cycles();
|
self.calculate_instant().0
|
||||||
self.calculate_instant(instant_cycles)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,22 +165,22 @@ pub struct Instant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Instant {
|
impl Instant {
|
||||||
/// Create a zeroed `Instant`.
|
/// Creates a zeroed `Instant`.
|
||||||
pub const fn zero() -> Self {
|
pub const fn zero() -> Self {
|
||||||
Self { secs: 0, nanos: 0 }
|
Self { secs: 0, nanos: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an new `Instant` based on the inputting `secs` and `nanos`.
|
/// Creates an new `Instant` based on the inputting `secs` and `nanos`.
|
||||||
pub fn new(secs: u64, nanos: u32) -> Self {
|
pub fn new(secs: u64, nanos: u32) -> Self {
|
||||||
Self { secs, nanos }
|
Self { secs, nanos }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the seconds recorded in the Instant.
|
/// Returns the seconds recorded in the Instant.
|
||||||
pub fn secs(&self) -> u64 {
|
pub fn secs(&self) -> u64 {
|
||||||
self.secs
|
self.secs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the nanoseconds recorded in the Instant.
|
/// Returns the nanoseconds recorded in the Instant.
|
||||||
pub fn nanos(&self) -> u32 {
|
pub fn nanos(&self) -> u32 {
|
||||||
self.nanos
|
self.nanos
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user