1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
pub use self::inner::SteadyTime;
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
use libc;
use time::Duration;
use ops::Sub;
use sync::{Once, ONCE_INIT};
pub struct SteadyTime {
t: u64
}
extern {
pub fn mach_absolute_time() -> u64;
pub fn mach_timebase_info(info: *mut libc::mach_timebase_info) -> libc::c_int;
}
impl SteadyTime {
pub fn now() -> SteadyTime {
SteadyTime {
t: unsafe { mach_absolute_time() },
}
}
pub fn ns(&self) -> u64 {
let info = info();
self.t * info.numer as u64 / info.denom 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_INIT;
unsafe {
ONCE.call_once(|| {
mach_timebase_info(&mut INFO);
});
&INFO
}
}
impl<'a> Sub for &'a SteadyTime {
type Output = Duration;
fn sub(self, other: &SteadyTime) -> Duration {
let info = info();
let diff = self.t as i64 - other.t as i64;
Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64)
}
}
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
use libc;
use time::Duration;
use ops::Sub;
const NSEC_PER_SEC: i64 = 1_000_000_000;
pub struct SteadyTime {
t: libc::timespec,
}
#[cfg(not(any(target_os = "android",
target_os = "bitrig",
target_os = "openbsd")))]
#[link(name = "rt")]
extern {}
extern {
fn clock_gettime(clk_id: libc::c_int, tp: *mut libc::timespec) -> libc::c_int;
}
impl SteadyTime {
pub fn now() -> SteadyTime {
let mut t = SteadyTime {
t: libc::timespec {
tv_sec: 0,
tv_nsec: 0,
}
};
unsafe {
assert_eq!(0, clock_gettime(libc::CLOCK_MONOTONIC, &mut t.t));
}
t
}
pub fn ns(&self) -> u64 {
self.t.tv_sec as u64 * NSEC_PER_SEC as u64 + self.t.tv_nsec as u64
}
}
impl<'a> Sub for &'a SteadyTime {
type Output = Duration;
fn sub(self, other: &SteadyTime) -> Duration {
if self.t.tv_nsec >= other.t.tv_nsec {
Duration::seconds(self.t.tv_sec as i64 - other.t.tv_sec as i64) +
Duration::nanoseconds(self.t.tv_nsec as i64 - other.t.tv_nsec as i64)
} else {
Duration::seconds(self.t.tv_sec as i64 - 1 - other.t.tv_sec as i64) +
Duration::nanoseconds(self.t.tv_nsec as i64 + NSEC_PER_SEC -
other.t.tv_nsec as i64)
}
}
}
}