mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 17:44:10 +00:00
devices: pit: remove clock_gettime() usage
The original Pit code encoded the start value of a timer into the count_load_time field as a number of nanoseconds since the start of the host's monotonic time value. Instead, we can use the PitCounter's creation_time as the epoch. This makes the math look a bit more sensible and removes the use of the non-portable clock_gettime() function. Before ====== get_channel_state(): count_load_time = get_monotonic_time() - start.elapsed() === count_load_time = now() - (now() - start) === count_load_time = start set_channel_state(): start = now() - (get_monotonic_time() - count_load_time) === start = now() - now() + count_load_time === start = count_load_time After ===== get_channel_state(): count_load_time = start - creation_time set_channel_state(): start = creation_time + count_load_time BUG=chromium:908689 BUG=b:213149155 TEST=cargo test -p devices pit TEST=tools/run_tests --target=host --arch=win64 Change-Id: I5468d1d964a04b1ce96979ed583b729d139e1005 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3723804 Reviewed-by: Noah Gold <nkgold@google.com> Reviewed-by: Vikram Auradkar <auradkar@google.com> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
aeea40d6ff
commit
e5c6e65731
3 changed files with 44 additions and 34 deletions
|
@ -24,10 +24,22 @@ impl Clock {
|
|||
self.0.duration_since(earlier.0)
|
||||
}
|
||||
|
||||
pub fn checked_duration_since(&self, earlier: &Self) -> Option<Duration> {
|
||||
self.0.checked_duration_since(earlier.0)
|
||||
}
|
||||
|
||||
pub fn saturating_duration_since(&self, earlier: &Self) -> Duration {
|
||||
self.0.saturating_duration_since(earlier.0)
|
||||
}
|
||||
|
||||
pub fn elapsed(&self) -> Duration {
|
||||
self.0.elapsed()
|
||||
}
|
||||
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Self> {
|
||||
Some(Clock(self.0.checked_add(duration)?))
|
||||
}
|
||||
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
|
||||
Some(Clock(self.0.checked_sub(duration)?))
|
||||
}
|
||||
|
@ -71,8 +83,22 @@ impl FakeClock {
|
|||
|
||||
/// Get the duration since |earlier|, assuming that earlier < self.
|
||||
pub fn duration_since(&self, earlier: &Self) -> Duration {
|
||||
let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
|
||||
Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
|
||||
self.checked_duration_since(earlier).unwrap()
|
||||
}
|
||||
|
||||
/// Get the duration since |earlier|
|
||||
pub fn checked_duration_since(&self, earlier: &Self) -> Option<Duration> {
|
||||
let ns_diff = self.ns_since_epoch.checked_sub(earlier.ns_since_epoch)?;
|
||||
Some(Duration::new(
|
||||
ns_diff / NS_PER_SEC,
|
||||
(ns_diff % NS_PER_SEC) as u32,
|
||||
))
|
||||
}
|
||||
|
||||
/// Get the duration since |earlier|, or 0 if earlier < self.
|
||||
pub fn saturating_duration_since(&self, earlier: &Self) -> Duration {
|
||||
self.checked_duration_since(earlier)
|
||||
.unwrap_or(Duration::ZERO)
|
||||
}
|
||||
|
||||
/// Get the time that has elapsed since this clock was made. Always returns 0 on a FakeClock.
|
||||
|
@ -80,6 +106,15 @@ impl FakeClock {
|
|||
self.now().duration_since(self)
|
||||
}
|
||||
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Self> {
|
||||
Some(FakeClock {
|
||||
ns_since_epoch: self
|
||||
.ns_since_epoch
|
||||
.checked_add(duration.as_nanos() as u64)?,
|
||||
deadlines: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
|
||||
Some(FakeClock {
|
||||
ns_since_epoch: self
|
||||
|
|
|
@ -10,6 +10,8 @@ mod bus;
|
|||
mod irq_event;
|
||||
pub mod irqchip;
|
||||
mod pci;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod pit;
|
||||
pub mod serial_device;
|
||||
mod sys;
|
||||
pub mod virtio;
|
||||
|
@ -28,6 +30,8 @@ pub use self::pci::{
|
|||
PciDeviceError, PciInterruptPin, PciRoot, PciVirtualConfigMmio, StubPciDevice,
|
||||
StubPciParameters,
|
||||
};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub use self::pit::{Pit, PitError};
|
||||
#[cfg(all(feature = "tpm", feature = "chromeos", target_arch = "x86_64"))]
|
||||
pub use self::vtpm_proxy::VtpmProxy;
|
||||
|
||||
|
@ -41,8 +45,6 @@ cfg_if::cfg_if! {
|
|||
#[cfg(feature = "direct")]
|
||||
pub mod direct_irq;
|
||||
mod i8042;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod pit;
|
||||
pub mod pl030;
|
||||
mod platform;
|
||||
mod proxy;
|
||||
|
@ -80,8 +82,6 @@ cfg_if::cfg_if! {
|
|||
PvPanicCode, PcieRootPort, PcieHostPort,
|
||||
PvPanicPciDevice, VfioPciDevice, PciBridge,
|
||||
};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub use self::pit::{Pit, PitError};
|
||||
pub use self::pl030::Pl030;
|
||||
pub use self::platform::VfioPlatformDevice;
|
||||
pub use self::proxy::Error as ProxyError;
|
||||
|
|
|
@ -435,21 +435,6 @@ fn adjust_count(count: u32) -> u32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the current monotonic time of host in nanoseconds
|
||||
fn get_monotonic_time() -> u64 {
|
||||
let mut time = libc::timespec {
|
||||
tv_sec: 0,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
// Safe because time struct is local to this function and we check the returncode
|
||||
let ret = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut time) };
|
||||
if ret != 0 {
|
||||
0
|
||||
} else {
|
||||
time.tv_sec as u64 * 1_000_000_000u64 + time.tv_nsec as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl PitCounter {
|
||||
fn new(
|
||||
counter_id: usize,
|
||||
|
@ -485,11 +470,8 @@ impl PitCounter {
|
|||
}
|
||||
|
||||
fn get_channel_state(&self) -> PitChannelState {
|
||||
// Crosvm Pit stores start as an Instant. We do our best to convert to the host's
|
||||
// monotonic clock by taking the current monotonic time and subtracting the elapsed
|
||||
// time since self.start.
|
||||
let load_time = match &self.start {
|
||||
Some(t) => get_monotonic_time() - t.elapsed().as_nanos() as u64,
|
||||
Some(t) => t.saturating_duration_since(&self.creation_time).as_nanos() as u64,
|
||||
None => 0,
|
||||
};
|
||||
|
||||
|
@ -566,16 +548,9 @@ impl PitCounter {
|
|||
self.read_low_byte = state.read_state == PitRWState::Word1;
|
||||
self.wrote_low_byte = state.write_state == PitRWState::Word1;
|
||||
|
||||
// To convert the count_load_time to an instant we have to convert it to a
|
||||
// duration by comparing it to get_monotonic_time. Then subtract that duration from
|
||||
// a "now" instant.
|
||||
self.start = self
|
||||
.clock
|
||||
.lock()
|
||||
.now()
|
||||
.checked_sub(std::time::Duration::from_nanos(
|
||||
get_monotonic_time() - state.count_load_time,
|
||||
));
|
||||
.creation_time
|
||||
.checked_add(Duration::from_nanos(state.count_load_time));
|
||||
}
|
||||
|
||||
fn get_access_mode(&self) -> Option<CommandAccess> {
|
||||
|
|
Loading…
Reference in a new issue