From f2a90174bb36b9ad528e863ab34c02ebce002b02 Mon Sep 17 00:00:00 2001 From: Valentin Date: Fri, 15 Jun 2018 18:57:24 +0200 Subject: Update for latest nightly 2018-06-09 (#70) * Update for latest nightly 2018-06-09 * We now have a proper horizon os and sys modules in libstd --- ctr-std/src/sys/unix/time.rs | 226 +++++++++++++++++++++++++++++-------------- 1 file changed, 153 insertions(+), 73 deletions(-) (limited to 'ctr-std/src/sys/unix/time.rs') diff --git a/ctr-std/src/sys/unix/time.rs b/ctr-std/src/sys/unix/time.rs index d5dcbc4..89786eb 100644 --- a/ctr-std/src/sys/unix/time.rs +++ b/ctr-std/src/sys/unix/time.rs @@ -14,6 +14,7 @@ use time::Duration; use core::hash::{Hash, Hasher}; pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; +use convert::TryInto; const NSEC_PER_SEC: u64 = 1_000_000_000; @@ -42,8 +43,12 @@ impl Timespec { } fn add_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); + let mut secs = other + .as_secs() + .try_into() // <- target type would be `libc::time_t` + .ok() + .and_then(|secs| self.t.tv_sec.checked_add(secs)) + .expect("overflow when adding duration to time"); // Nano calculations can't overflow because nanos are <1B which fit // in a u32. @@ -55,16 +60,19 @@ impl Timespec { } Timespec { t: libc::timespec { - tv_sec: secs as libc::time_t, - tv_nsec: nsec as libc::c_long, + tv_sec: secs, + tv_nsec: nsec as _, }, } } fn sub_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); + let mut secs = other + .as_secs() + .try_into() // <- target type would be `libc::time_t` + .ok() + .and_then(|secs| self.t.tv_sec.checked_sub(secs)) + .expect("overflow when subtracting duration from time"); // Similar to above, nanos can't overflow. let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; @@ -75,8 +83,8 @@ impl Timespec { } Timespec { t: libc::timespec { - tv_sec: secs as libc::time_t, - tv_nsec: nsec as libc::c_long, + tv_sec: secs, + tv_nsec: nsec as _, }, } } @@ -111,6 +119,7 @@ impl Hash for Timespec { } } +#[cfg(any(target_os = "macos", target_os = "ios"))] mod inner { use fmt; use libc; @@ -122,8 +131,6 @@ mod inner { use super::NSEC_PER_SEC; use super::Timespec; - use libctru; - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant { t: u64 @@ -145,7 +152,7 @@ mod inner { impl Instant { pub fn now() -> Instant { - Instant { t: ctr_absolute_time() } + Instant { t: unsafe { libc::mach_absolute_time() } } } pub fn sub_instant(&self, other: &Instant) -> Duration { @@ -166,71 +173,11 @@ mod inner { pub fn sub_duration(&self, other: &Duration) -> Instant { Instant { t: self.t.checked_sub(dur2intervals(other)) - .expect("overflow when adding duration to instant"), + .expect("overflow when subtracting duration from instant"), } } } - // The initial system tick after which all Instants occur - static mut TICK: u64 = 0; - - // A source of monotonic time based on ticks of the 3DS CPU. Returns the - // number of system ticks elapsed since an arbitrary point in the past - fn ctr_absolute_time() -> u64 { - let first_tick = get_first_tick(); - let current_tick = get_system_tick(); - current_tick - first_tick - } - - // The first time this function is called, it generates and returns the - // initial system tick used to create Instants - // - // subsequent calls to this function return the previously generated - // tick value - fn get_first_tick() -> u64 { - static ONCE: Once = Once::new(); - unsafe { - ONCE.call_once(|| { - TICK = get_system_tick(); - }); - TICK - } - } - - // Gets the current system tick - #[inline] - fn get_system_tick() -> u64 { - unsafe { libctru::svcGetSystemTick() } - } - - // A struct representing the clock speed of the 3DS - struct CtrClockInfo { - numer: u32, - denom: u32, - } - - // Initializes the CtrClockInfo struct - // - // Note that svcGetSystemTick always runs at 268MHz (268,111,856Hz), even - // on a New 3DS running in 804MHz mode - // - // See https://www.3dbrew.org/wiki/Hardware#Common_hardware - fn info() -> &'static CtrClockInfo { - static INFO: CtrClockInfo = CtrClockInfo { - numer: 1_000_000_000, - denom: 268_111_856, - }; - &INFO - } - - fn dur2intervals(dur: &Duration) -> u64 { - let info = info(); - let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| { - nanos.checked_add(dur.subsec_nanos() as u64) - }).expect("overflow converting duration to nanoseconds"); - mul_div_u64(nanos, info.denom as u64, info.numer as u64) - } - impl SystemTime { pub fn now() -> SystemTime { use ptr; @@ -282,4 +229,137 @@ mod inner { .finish() } } + + fn dur2intervals(dur: &Duration) -> u64 { + let info = info(); + let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| { + nanos.checked_add(dur.subsec_nanos() as u64) + }).expect("overflow converting duration to nanoseconds"); + mul_div_u64(nanos, info.denom as u64, info.numer as u64) + } + + fn info() -> &'static libc::mach_timebase_info { + static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info { + numer: 0, + denom: 0, + }; + static ONCE: Once = Once::new(); + + unsafe { + ONCE.call_once(|| { + libc::mach_timebase_info(&mut INFO); + }); + &INFO + } + } +} + +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +mod inner { + use fmt; + use libc; + use sys::cvt; + use time::Duration; + + use super::Timespec; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Instant { + t: Timespec, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct SystemTime { + t: Timespec, + } + + pub const UNIX_EPOCH: SystemTime = SystemTime { + t: Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }, + }, + }; + + impl Instant { + pub fn now() -> Instant { + Instant { t: now(libc::CLOCK_MONOTONIC) } + } + + pub fn sub_instant(&self, other: &Instant) -> Duration { + self.t.sub_timespec(&other.t).unwrap_or_else(|_| { + panic!("specified instant was later than self") + }) + } + + pub fn add_duration(&self, other: &Duration) -> Instant { + Instant { t: self.t.add_duration(other) } + } + + pub fn sub_duration(&self, other: &Duration) -> Instant { + Instant { t: self.t.sub_duration(other) } + } + } + + impl fmt::Debug for Instant { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Instant") + .field("tv_sec", &self.t.t.tv_sec) + .field("tv_nsec", &self.t.t.tv_nsec) + .finish() + } + } + + impl SystemTime { + pub fn now() -> SystemTime { + SystemTime { t: now(libc::CLOCK_REALTIME) } + } + + pub fn sub_time(&self, other: &SystemTime) + -> Result { + self.t.sub_timespec(&other.t) + } + + pub fn add_duration(&self, other: &Duration) -> SystemTime { + SystemTime { t: self.t.add_duration(other) } + } + + pub fn sub_duration(&self, other: &Duration) -> SystemTime { + SystemTime { t: self.t.sub_duration(other) } + } + } + + impl From for SystemTime { + fn from(t: libc::timespec) -> SystemTime { + SystemTime { t: Timespec { t: t } } + } + } + + impl fmt::Debug for SystemTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("SystemTime") + .field("tv_sec", &self.t.t.tv_sec) + .field("tv_nsec", &self.t.t.tv_nsec) + .finish() + } + } + + #[cfg(not(target_os = "dragonfly"))] + pub type clock_t = libc::c_int; + #[cfg(target_os = "dragonfly")] + pub type clock_t = libc::c_ulong; + + fn now(clock: clock_t) -> Timespec { + let mut t = Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, + } + }; + cvt(unsafe { + libc::clock_gettime(clock, &mut t.t) + }).unwrap(); + t + } } -- cgit v1.2.3