12
12
13
13
use std:: io:: Reader ;
14
14
use std:: io:: mem:: BufReader ;
15
+ use std:: libc;
15
16
use std:: num;
16
17
use std:: str;
17
18
18
19
static NSEC_PER_SEC : i32 = 1_000_000_000_i32 ;
19
20
20
- pub mod rustrt {
21
+ mod rustrt {
21
22
use super :: Tm ;
22
23
23
24
extern {
24
- pub fn rust_get_time ( sec : & mut i64 , nsec : & mut i32 ) ;
25
- pub fn rust_precise_time_ns ( ns : & mut u64 ) ;
26
25
pub fn rust_tzset ( ) ;
27
26
pub fn rust_gmtime ( sec : i64 , nsec : i32 , result : & mut Tm ) ;
28
27
pub fn rust_localtime ( sec : i64 , nsec : i32 , result : & mut Tm ) ;
@@ -31,6 +30,31 @@ pub mod rustrt {
31
30
}
32
31
}
33
32
33
+ #[ cfg( unix, not( target_os = "macos" ) ) ]
34
+ mod imp {
35
+ use std:: libc:: { c_int, timespec} ;
36
+
37
+ // Apparently android provides this in some other library?
38
+ #[ cfg( not( target_os = "android" ) ) ]
39
+ #[ link( name = "rt" ) ]
40
+ extern { }
41
+
42
+ extern {
43
+ pub fn clock_gettime ( clk_id : c_int , tp : * mut timespec ) -> c_int ;
44
+ }
45
+
46
+ }
47
+ #[ cfg( target_os = "macos" ) ]
48
+ mod imp {
49
+ use std:: libc:: { timeval, timezone, c_int, mach_timebase_info} ;
50
+
51
+ extern {
52
+ pub fn gettimeofday ( tp : * mut timeval , tzp : * mut timezone ) -> c_int ;
53
+ pub fn mach_absolute_time ( ) -> u64 ;
54
+ pub fn mach_timebase_info ( info : * mut mach_timebase_info ) -> c_int ;
55
+ }
56
+ }
57
+
34
58
/// A record specifying a time value in seconds and nanoseconds.
35
59
36
60
@@ -64,11 +88,45 @@ impl Ord for Timespec {
64
88
*/
65
89
pub fn get_time ( ) -> Timespec {
66
90
unsafe {
67
- let mut sec = 0i64 ;
68
- let mut nsec = 0i32 ;
69
- rustrt:: rust_get_time ( & mut sec, & mut nsec) ;
91
+ let ( sec, nsec) = os_get_time ( ) ;
70
92
return Timespec :: new ( sec, nsec) ;
71
93
}
94
+
95
+ #[ cfg( windows) ]
96
+ unsafe fn os_get_time ( ) -> ( i64 , i32 ) {
97
+ static NANOSECONDS_FROM_1601_TO_1970 : u64 = 11644473600000000 ;
98
+
99
+ let mut time = libc:: FILETIME {
100
+ dwLowDateTime : 0 ,
101
+ dwHighDateTime : 0 ,
102
+ } ;
103
+ libc:: GetSystemTimeAsFileTime ( & mut time) ;
104
+
105
+ // A FILETIME contains a 64-bit value representing the number of
106
+ // hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z.
107
+ // http://support.microsoft.com/kb/167296/en-us
108
+ let ns_since_1601 = ( ( time. dwHighDateTime as u64 << 32 ) |
109
+ ( time. dwLowDateTime as u64 << 0 ) ) / 10 ;
110
+ let ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970 ;
111
+
112
+ ( ( ns_since_1970 / 1000000 ) as i64 ,
113
+ ( ( ns_since_1970 % 1000000 ) * 1000 ) as i32 )
114
+ }
115
+
116
+ #[ cfg( target_os = "macos" ) ]
117
+ unsafe fn os_get_time ( ) -> ( i64 , i32 ) {
118
+ use std:: ptr;
119
+ let mut tv = libc:: timeval { tv_sec : 0 , tv_usec : 0 } ;
120
+ imp:: gettimeofday ( & mut tv, ptr:: mut_null ( ) ) ;
121
+ ( tv. tv_sec as i64 , tv. tv_usec * 1000 )
122
+ }
123
+
124
+ #[ cfg( not( target_os = "macos" ) , not( windows) ) ]
125
+ unsafe fn os_get_time ( ) -> ( i64 , i32 ) {
126
+ let mut tv = libc:: timespec { tv_sec : 0 , tv_nsec : 0 } ;
127
+ imp:: clock_gettime ( libc:: CLOCK_REALTIME , & mut tv) ;
128
+ ( tv. tv_sec as i64 , tv. tv_nsec as i32 )
129
+ }
72
130
}
73
131
74
132
@@ -77,10 +135,38 @@ pub fn get_time() -> Timespec {
77
135
* in nanoseconds since an unspecified epoch.
78
136
*/
79
137
pub fn precise_time_ns ( ) -> u64 {
80
- unsafe {
81
- let mut ns = 0u64 ;
82
- rustrt:: rust_precise_time_ns ( & mut ns) ;
83
- ns
138
+ return os_precise_time_ns ( ) ;
139
+
140
+ #[ cfg( windows) ]
141
+ fn os_precise_time_ns ( ) -> u64 {
142
+ let mut ticks_per_s = 0 ;
143
+ assert_eq ! ( unsafe {
144
+ libc:: QueryPerformanceFrequency ( & mut ticks_per_s)
145
+ } , 1 ) ;
146
+ let ticks_per_s = if ticks_per_s == 0 { 1 } else { ticks_per_s} ;
147
+ let mut ticks = 0 ;
148
+ assert_eq ! ( unsafe {
149
+ libc:: QueryPerformanceCounter ( & mut ticks)
150
+ } , 1 ) ;
151
+
152
+ return ( ticks as u64 * 1000000000 ) / ( ticks_per_s as u64 ) ;
153
+ }
154
+
155
+ #[ cfg( target_os = "macos" ) ]
156
+ fn os_precise_time_ns ( ) -> u64 {
157
+ let time = unsafe { imp:: mach_absolute_time ( ) } ;
158
+ let mut info = libc:: mach_timebase_info { numer : 0 , denom : 0 } ;
159
+ unsafe { imp:: mach_timebase_info ( & mut info) ; }
160
+ return time * ( ( info. numer / info. denom ) as u64 ) ;
161
+ }
162
+
163
+ #[ cfg( not( windows) , not( target_os = "macos" ) ) ]
164
+ fn os_precise_time_ns ( ) -> u64 {
165
+ let mut ts = libc:: timespec { tv_sec : 0 , tv_nsec : 0 } ;
166
+ unsafe {
167
+ imp:: clock_gettime ( libc:: CLOCK_MONOTONIC , & mut ts) ;
168
+ }
169
+ return ( ts. tv_sec as u64 ) * 1000000000 + ( ts. tv_nsec as u64 )
84
170
}
85
171
}
86
172
0 commit comments