abi: fix bug in checked_sub_duration(), add tests
This commit is contained in:
parent
dc76c5b7a8
commit
97e11c3bee
@ -127,7 +127,7 @@ impl Ext2Fs {
|
||||
|
||||
// Free inode blocks
|
||||
inode.resize(self, 0).await?;
|
||||
inode.dtime = real_time().seconds as u32;
|
||||
inode.dtime = real_time().seconds() as u32;
|
||||
|
||||
self.write_inode(ino, inode).await?;
|
||||
|
||||
|
@ -199,7 +199,7 @@ impl InodeAccess {
|
||||
log::info!("ext2: allocated inode #{ino}");
|
||||
|
||||
let cache = fs.inode_cache.get().clone();
|
||||
let now = real_time().seconds as u32;
|
||||
let now = real_time().seconds() as u32;
|
||||
|
||||
let mut imode = InodeMode::default_for_type(ty);
|
||||
imode.update_permissions(mode);
|
||||
|
@ -78,7 +78,7 @@ pub fn range(a: u64, b: u64) -> u64 {
|
||||
/// Initializes the random generator state
|
||||
pub fn init() {
|
||||
let now = monotonic_time();
|
||||
let random_seed = now.nanoseconds.wrapping_add(now.seconds);
|
||||
let random_seed = now.subsec_nanos().wrapping_add(now.seconds());
|
||||
|
||||
let mut state = RandomState::new(random_seed as u32);
|
||||
state.fill_buf();
|
||||
|
@ -14,9 +14,8 @@ static REAL_TIME: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
#[inline]
|
||||
fn make_time(ticks: u64) -> SystemTime {
|
||||
SystemTime {
|
||||
seconds: ticks / NANOSECONDS_IN_SECOND,
|
||||
nanoseconds: ticks % NANOSECONDS_IN_SECOND,
|
||||
unsafe {
|
||||
SystemTime::new_unchecked(ticks / NANOSECONDS_IN_SECOND, ticks % NANOSECONDS_IN_SECOND)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,10 +32,7 @@ pub fn real_time() -> SystemTime {
|
||||
debug_assert!(nanoseconds < NANOSECONDS_IN_SECOND);
|
||||
}
|
||||
|
||||
SystemTime {
|
||||
seconds,
|
||||
nanoseconds,
|
||||
}
|
||||
unsafe { SystemTime::new_unchecked(seconds, nanoseconds) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -148,7 +148,7 @@ pub struct Node {
|
||||
|
||||
impl Metadata {
|
||||
pub fn now(uid: UserId, gid: GroupId, mode: FileMode) -> Metadata {
|
||||
let now = real_time().seconds;
|
||||
let now = real_time().seconds();
|
||||
Metadata {
|
||||
mode,
|
||||
uid,
|
||||
|
@ -11,8 +11,9 @@
|
||||
// TODO temporary
|
||||
#![allow(missing_docs)]
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "rustc-dep-of-std")))]
|
||||
#[cfg(all(any(feature = "alloc", test), not(feature = "rustc-dep-of-std")))]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "rustc-dep-of-std")]
|
||||
extern crate rustc_std_alloc as alloc;
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
use core::{ops::Add, time::Duration};
|
||||
use core::{
|
||||
ops::{Add, Sub},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use abi_lib::SyscallRegister;
|
||||
|
||||
@ -8,8 +11,8 @@ pub const MILLISECONDS_IN_SECOND: u64 = 1_000;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct SystemTime {
|
||||
pub seconds: u64,
|
||||
pub nanoseconds: u64,
|
||||
seconds: u64,
|
||||
nanoseconds: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
@ -18,13 +21,6 @@ pub enum ClockType {
|
||||
RealTime,
|
||||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const ZERO: Self = Self {
|
||||
seconds: 0,
|
||||
nanoseconds: 0,
|
||||
};
|
||||
}
|
||||
|
||||
impl SyscallRegister for ClockType {
|
||||
fn into_syscall_register(self) -> usize {
|
||||
match self {
|
||||
@ -43,11 +39,52 @@ impl SyscallRegister for ClockType {
|
||||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const ZERO: Self = Self {
|
||||
seconds: 0,
|
||||
nanoseconds: 0,
|
||||
};
|
||||
|
||||
pub unsafe fn new_unchecked(seconds: u64, nanoseconds: u64) -> Self {
|
||||
Self {
|
||||
seconds,
|
||||
nanoseconds,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(seconds: u64, nanoseconds: u64) -> Self {
|
||||
Self::new_opt(seconds, nanoseconds).unwrap()
|
||||
}
|
||||
|
||||
pub fn new_opt(mut seconds: u64, nanoseconds: u64) -> Option<Self> {
|
||||
seconds = seconds.checked_add(nanoseconds / NANOSECONDS_IN_SECOND)?;
|
||||
Some(Self {
|
||||
seconds,
|
||||
nanoseconds: nanoseconds % NANOSECONDS_IN_SECOND,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_seconds(seconds: u64) -> Self {
|
||||
Self {
|
||||
seconds,
|
||||
nanoseconds: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_millis(&self) -> u128 {
|
||||
(self.seconds as u128 * MILLISECONDS_IN_SECOND as u128)
|
||||
+ (self.nanoseconds as u128 / 1000000)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn subsec_nanos(&self) -> u64 {
|
||||
self.nanoseconds
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn seconds(&self) -> u64 {
|
||||
self.seconds
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Self> {
|
||||
let nanoseconds = self.nanoseconds.checked_add(other.subsec_nanos() as u64)?;
|
||||
let seconds = nanoseconds / NANOSECONDS_IN_SECOND;
|
||||
@ -67,7 +104,7 @@ impl SystemTime {
|
||||
let mut seconds = self.seconds.checked_sub(other.as_secs())?;
|
||||
let nanoseconds = if self.nanoseconds < other.subsec_nanos() as u64 {
|
||||
seconds = seconds.checked_sub(1)?;
|
||||
NANOSECONDS_IN_SECOND + self.seconds - other.subsec_nanos() as u64
|
||||
NANOSECONDS_IN_SECOND + self.nanoseconds - other.subsec_nanos() as u64
|
||||
} else {
|
||||
self.nanoseconds - other.subsec_nanos() as u64
|
||||
};
|
||||
@ -105,15 +142,18 @@ impl SystemTime {
|
||||
impl Add<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
#[inline]
|
||||
fn add(self, rhs: Duration) -> Self::Output {
|
||||
let mut seconds = self.seconds + rhs.as_secs();
|
||||
let mut nanoseconds = self.nanoseconds + rhs.subsec_nanos() as u64;
|
||||
seconds += nanoseconds / NANOSECONDS_IN_SECOND;
|
||||
nanoseconds %= NANOSECONDS_IN_SECOND;
|
||||
Self {
|
||||
seconds,
|
||||
nanoseconds,
|
||||
}
|
||||
self.checked_add_duration(&rhs).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, rhs: Duration) -> Self::Output {
|
||||
self.checked_sub_duration(&rhs).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,19 +161,72 @@ impl Add<Duration> for SystemTime {
|
||||
mod tests {
|
||||
use core::time::Duration;
|
||||
|
||||
use super::SystemTime;
|
||||
use super::{SystemTime, NANOSECONDS_IN_SECOND};
|
||||
|
||||
#[test]
|
||||
fn test_system_time_math() {
|
||||
let t0 = SystemTime {
|
||||
seconds: 1,
|
||||
nanoseconds: 123000000,
|
||||
};
|
||||
let t1 = SystemTime {
|
||||
seconds: 1,
|
||||
nanoseconds: 143000000,
|
||||
};
|
||||
assert_eq!(t0 + Duration::from_millis(20), t1);
|
||||
assert_eq!(t1.as_millis(), 1143);
|
||||
fn time_sub_time() {
|
||||
let t0 = SystemTime::new(1, NANOSECONDS_IN_SECOND - 1);
|
||||
let t1 = SystemTime::new(2, 0);
|
||||
|
||||
assert_eq!(t0.sub_time(&t1).unwrap_err(), Duration::new(0, 1));
|
||||
assert_eq!(t1.sub_time(&t0).unwrap(), Duration::new(0, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_checked_sub_time() {
|
||||
let t0 = SystemTime::new(1, NANOSECONDS_IN_SECOND - 1);
|
||||
let t1 = SystemTime::new(2, 0);
|
||||
|
||||
assert!(t0.checked_sub_time(&t1).is_none());
|
||||
assert_eq!(t1.checked_sub_time(&t0).unwrap(), Duration::new(0, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_sub_duration() {
|
||||
let t0 = SystemTime::new(2, 1);
|
||||
|
||||
assert_eq!(
|
||||
t0.checked_sub_duration(&Duration::new(1, 1)).unwrap(),
|
||||
SystemTime::new(1, 0)
|
||||
);
|
||||
assert_eq!(
|
||||
t0.checked_sub_duration(&Duration::new(1, 2)).unwrap(),
|
||||
SystemTime::new(0, NANOSECONDS_IN_SECOND - 1)
|
||||
);
|
||||
assert_eq!(
|
||||
t0.checked_sub_duration(&Duration::new(1, NANOSECONDS_IN_SECOND as u32 - 1))
|
||||
.unwrap(),
|
||||
SystemTime::new(0, 2)
|
||||
);
|
||||
assert_eq!(
|
||||
t0.checked_sub_duration(&Duration::new(2, 1)).unwrap(),
|
||||
SystemTime::ZERO
|
||||
);
|
||||
assert!(t0.checked_sub_duration(&Duration::new(2, 2)).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_add_duration() {
|
||||
let t0 = SystemTime::new(2, 1);
|
||||
let t1 = SystemTime::new(u64::MAX, 1);
|
||||
|
||||
assert_eq!(
|
||||
t0.checked_add_duration(&Duration::new(1, 0)).unwrap(),
|
||||
SystemTime::new(3, 1)
|
||||
);
|
||||
assert_eq!(
|
||||
t0.checked_add_duration(&Duration::new(1, NANOSECONDS_IN_SECOND as u32 - 1))
|
||||
.unwrap(),
|
||||
SystemTime::new(4, 0)
|
||||
);
|
||||
assert_eq!(
|
||||
t1.checked_add_duration(&Duration::new(0, NANOSECONDS_IN_SECOND as u32 - 2))
|
||||
.unwrap(),
|
||||
SystemTime::new(u64::MAX, NANOSECONDS_IN_SECOND - 1)
|
||||
);
|
||||
assert!(t1
|
||||
.checked_add_duration(&Duration::new(0, NANOSECONDS_IN_SECOND as u32 - 1))
|
||||
.is_none());
|
||||
assert!(t1.checked_add_duration(&Duration::new(1, 0)).is_none());
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ enum Error {
|
||||
|
||||
fn run() -> Result<(), Error> {
|
||||
let now = get_real_time().map_err(Error::GetTime)?;
|
||||
let now = DateTime::from_timestamp(now.seconds as _, now.nanoseconds as _).ok_or(Error::UtcTime)?;
|
||||
let now = DateTime::from_timestamp(now.seconds() as _, now.subsec_nanos() as _).ok_or(Error::UtcTime)?;
|
||||
println!("{now}");
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user