Skip to content

Commit 5ff7b28

Browse files
committed
auto merge of #11208 : alexcrichton/rust/less-c, r=cmr
Right now on linux, an empty executable with LTO still depends on librt becaues of the clock_gettime function in rust_builtin.o, but this commit moves this dependency into a rust function which is subject to elimination via LTO. At the same time, this also drops libstd's dependency on librt on unices that are not OSX because the library is only used by extra::time (and now the dependency is listed in that module instead).
2 parents 250ca0e + 726091f commit 5ff7b28

File tree

5 files changed

+202
-87
lines changed

5 files changed

+202
-87
lines changed

src/libextra/time.rs

+96-10
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,16 @@
1212

1313
use std::io::Reader;
1414
use std::io::mem::BufReader;
15+
use std::libc;
1516
use std::num;
1617
use std::str;
1718

1819
static 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
*/
6589
pub 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
*/
79137
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)
84170
}
85171
}
86172

src/librustuv/uvll.rs

+4
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,10 @@ extern {
739739
#[link(name = "pthread")]
740740
extern {}
741741

742+
#[cfg(target_os = "linux")]
743+
#[link(name = "rt")]
744+
extern {}
745+
742746
#[cfg(target_os = "win32")]
743747
#[link(name = "ws2_32")]
744748
#[link(name = "psapi")]

0 commit comments

Comments
 (0)