1212
1313use std:: io:: Reader ;
1414use std:: io:: mem:: BufReader ;
15+ use std:: libc;
1516use std:: num;
1617use std:: str;
1718
1819static NSEC_PER_SEC : i32 = 1_000_000_000_i32 ;
1920
20- pub mod rustrt {
21+ mod rustrt {
2122 use super :: Tm ;
2223
2324 extern {
24- pub fn rust_get_time ( sec : & mut i64 , nsec : & mut i32 ) ;
25- pub fn rust_precise_time_ns ( ns : & mut u64 ) ;
2625 pub fn rust_tzset ( ) ;
2726 pub fn rust_gmtime ( sec : i64 , nsec : i32 , result : & mut Tm ) ;
2827 pub fn rust_localtime ( sec : i64 , nsec : i32 , result : & mut Tm ) ;
@@ -31,6 +30,31 @@ pub mod rustrt {
3130 }
3231}
3332
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+
3458/// A record specifying a time value in seconds and nanoseconds.
3559
3660
@@ -64,11 +88,45 @@ impl Ord for Timespec {
6488 */
6589pub fn get_time ( ) -> Timespec {
6690 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 ( ) ;
7092 return Timespec :: new ( sec, nsec) ;
7193 }
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+ }
72130}
73131
74132
@@ -77,10 +135,38 @@ pub fn get_time() -> Timespec {
77135 * in nanoseconds since an unspecified epoch.
78136 */
79137pub 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 )
84170 }
85171}
86172
0 commit comments