]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/unix/time.rs
Auto merge of #24865 - bluss:range-size, r=alexcrichton
[rust.git] / src / libstd / sys / unix / time.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use self::inner::SteadyTime;
12
13 #[cfg(any(target_os = "macos", target_os = "ios"))]
14 mod inner {
15     use libc;
16     use time::Duration;
17     use ops::Sub;
18     use sync::{Once, ONCE_INIT};
19
20     pub struct SteadyTime {
21         t: u64
22     }
23
24     extern {
25         pub fn mach_absolute_time() -> u64;
26         pub fn mach_timebase_info(info: *mut libc::mach_timebase_info) -> libc::c_int;
27     }
28
29     impl SteadyTime {
30         pub fn now() -> SteadyTime {
31             SteadyTime {
32                 t: unsafe { mach_absolute_time() },
33             }
34         }
35
36         pub fn ns(&self) -> u64 {
37             let info = info();
38             self.t * info.numer as u64 / info.denom as u64
39         }
40     }
41
42     fn info() -> &'static libc::mach_timebase_info {
43         static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
44             numer: 0,
45             denom: 0,
46         };
47         static ONCE: Once = ONCE_INIT;
48
49         unsafe {
50             ONCE.call_once(|| {
51                 mach_timebase_info(&mut INFO);
52             });
53             &INFO
54         }
55     }
56
57     impl<'a> Sub for &'a SteadyTime {
58         type Output = Duration;
59
60         fn sub(self, other: &SteadyTime) -> Duration {
61             let info = info();
62             let diff = self.t as i64 - other.t as i64;
63             Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64)
64         }
65     }
66 }
67
68 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
69 mod inner {
70     use libc;
71     use time::Duration;
72     use ops::Sub;
73
74     const NSEC_PER_SEC: i64 = 1_000_000_000;
75
76     pub struct SteadyTime {
77         t: libc::timespec,
78     }
79
80     // Apparently android provides this in some other library?
81     // Bitrig's RT extensions are in the C library, not a separate librt
82     // OpenBSD provide it via libc
83     #[cfg(not(any(target_os = "android",
84                   target_os = "bitrig",
85                   target_os = "openbsd",
86                   target_env = "musl")))]
87     #[link(name = "rt")]
88     extern {}
89
90     extern {
91         fn clock_gettime(clk_id: libc::c_int, tp: *mut libc::timespec) -> libc::c_int;
92     }
93
94     impl SteadyTime {
95         pub fn now() -> SteadyTime {
96             let mut t = SteadyTime {
97                 t: libc::timespec {
98                     tv_sec: 0,
99                     tv_nsec: 0,
100                 }
101             };
102             unsafe {
103                 assert_eq!(0, clock_gettime(libc::CLOCK_MONOTONIC, &mut t.t));
104             }
105             t
106         }
107
108         pub fn ns(&self) -> u64 {
109             self.t.tv_sec as u64 * NSEC_PER_SEC as u64 + self.t.tv_nsec as u64
110         }
111     }
112
113     impl<'a> Sub for &'a SteadyTime {
114         type Output = Duration;
115
116         fn sub(self, other: &SteadyTime) -> Duration {
117             if self.t.tv_nsec >= other.t.tv_nsec {
118                 Duration::seconds(self.t.tv_sec as i64 - other.t.tv_sec as i64) +
119                     Duration::nanoseconds(self.t.tv_nsec as i64 - other.t.tv_nsec as i64)
120             } else {
121                 Duration::seconds(self.t.tv_sec as i64 - 1 - other.t.tv_sec as i64) +
122                     Duration::nanoseconds(self.t.tv_nsec as i64 + NSEC_PER_SEC -
123                                           other.t.tv_nsec as i64)
124             }
125         }
126     }
127 }