use core::sync::atomic::{AtomicU64, Ordering}; use yggdrasil_abi::time::SystemTime; // Millisecond resolution const NANOSECONDS_IN_SECOND: u64 = 1_000_000_000; const TIME_RESOLUTION_NS: u64 = 1_000_000; pub const TICKS_PER_SEC: u64 = NANOSECONDS_IN_SECOND / TIME_RESOLUTION_NS; static MONOTONIC_TIME: AtomicU64 = AtomicU64::new(0); static REAL_TIME_OFFSET: AtomicU64 = AtomicU64::new(0); static REAL_TIME: AtomicU64 = AtomicU64::new(0); #[inline] fn make_time(ticks: u64) -> SystemTime { SystemTime { seconds: ticks / TICKS_PER_SEC, nanoseconds: (ticks % TICKS_PER_SEC) * TIME_RESOLUTION_NS, } } pub fn real_time() -> SystemTime { make_time(REAL_TIME.load(Ordering::Acquire) + REAL_TIME_OFFSET.load(Ordering::Relaxed)) } pub fn monotonic_time() -> SystemTime { make_time(MONOTONIC_TIME.load(Ordering::Acquire)) } pub fn add_ticks(ticks: u64) { MONOTONIC_TIME.fetch_add(ticks, Ordering::Release); REAL_TIME_OFFSET.fetch_add(ticks, Ordering::Release); } pub fn set_real_time(ticks: u64, reset: bool) { REAL_TIME.store(ticks, Ordering::Release); if reset { REAL_TIME_OFFSET.store(0, Ordering::Release); } } pub fn set_ticks(ticks: u64) { MONOTONIC_TIME.store(ticks, Ordering::Release); REAL_TIME_OFFSET.store(ticks, Ordering::Release); }