use std::io::Reader;
use std::io::mem::BufReader;
+use std::libc;
use std::num;
use std::str;
static NSEC_PER_SEC: i32 = 1_000_000_000_i32;
-pub mod rustrt {
+mod rustrt {
use super::Tm;
extern {
- pub fn rust_get_time(sec: &mut i64, nsec: &mut i32);
- pub fn rust_precise_time_ns(ns: &mut u64);
pub fn rust_tzset();
pub fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm);
pub fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm);
}
}
+#[cfg(unix, not(target_os = "macos"))]
+mod imp {
+ use std::libc::{c_int, timespec};
+
+ // Apparently android provides this in some other library?
+ #[cfg(not(target_os = "android"))]
+ #[link(name = "rt")]
+ extern {}
+
+ extern {
+ pub fn clock_gettime(clk_id: c_int, tp: *mut timespec) -> c_int;
+ }
+
+}
+#[cfg(target_os = "macos")]
+mod imp {
+ use std::libc::{timeval, timezone, c_int, mach_timebase_info};
+
+ extern {
+ pub fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int;
+ pub fn mach_absolute_time() -> u64;
+ pub fn mach_timebase_info(info: *mut mach_timebase_info) -> c_int;
+ }
+}
+
/// A record specifying a time value in seconds and nanoseconds.
*/
pub fn get_time() -> Timespec {
unsafe {
- let mut sec = 0i64;
- let mut nsec = 0i32;
- rustrt::rust_get_time(&mut sec, &mut nsec);
+ let (sec, nsec) = os_get_time();
return Timespec::new(sec, nsec);
}
+
+ #[cfg(windows)]
+ unsafe fn os_get_time() -> (i64, i32) {
+ static NANOSECONDS_FROM_1601_TO_1970: u64 = 11644473600000000;
+
+ let mut time = libc::FILETIME {
+ dwLowDateTime: 0,
+ dwHighDateTime: 0,
+ };
+ libc::GetSystemTimeAsFileTime(&mut time);
+
+ // A FILETIME contains a 64-bit value representing the number of
+ // hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z.
+ // http://support.microsoft.com/kb/167296/en-us
+ let ns_since_1601 = ((time.dwHighDateTime as u64 << 32) |
+ (time.dwLowDateTime as u64 << 0)) / 10;
+ let ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970;
+
+ ((ns_since_1970 / 1000000) as i64,
+ ((ns_since_1970 % 1000000) * 1000) as i32)
+ }
+
+ #[cfg(target_os = "macos")]
+ unsafe fn os_get_time() -> (i64, i32) {
+ use std::ptr;
+ let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
+ imp::gettimeofday(&mut tv, ptr::mut_null());
+ (tv.tv_sec as i64, tv.tv_usec * 1000)
+ }
+
+ #[cfg(not(target_os = "macos"), not(windows))]
+ unsafe fn os_get_time() -> (i64, i32) {
+ let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+ imp::clock_gettime(libc::CLOCK_REALTIME, &mut tv);
+ (tv.tv_sec as i64, tv.tv_nsec as i32)
+ }
}
* in nanoseconds since an unspecified epoch.
*/
pub fn precise_time_ns() -> u64 {
- unsafe {
- let mut ns = 0u64;
- rustrt::rust_precise_time_ns(&mut ns);
- ns
+ return os_precise_time_ns();
+
+ #[cfg(windows)]
+ fn os_precise_time_ns() -> u64 {
+ let mut ticks_per_s = 0;
+ assert_eq!(unsafe {
+ libc::QueryPerformanceFrequency(&mut ticks_per_s)
+ }, 1);
+ let ticks_per_s = if ticks_per_s == 0 {1} else {ticks_per_s};
+ let mut ticks = 0;
+ assert_eq!(unsafe {
+ libc::QueryPerformanceCounter(&mut ticks)
+ }, 1);
+
+ return (ticks as u64 * 1000000000) / (ticks_per_s as u64);
+ }
+
+ #[cfg(target_os = "macos")]
+ fn os_precise_time_ns() -> u64 {
+ let time = unsafe { imp::mach_absolute_time() };
+ let mut info = libc::mach_timebase_info { numer: 0, denom: 0 };
+ unsafe { imp::mach_timebase_info(&mut info); }
+ return time * ((info.numer / info.denom) as u64);
+ }
+
+ #[cfg(not(windows), not(target_os = "macos"))]
+ fn os_precise_time_ns() -> u64 {
+ let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+ unsafe {
+ imp::clock_gettime(libc::CLOCK_MONOTONIC, &mut ts);
+ }
+ return (ts.tv_sec as u64) * 1000000000 + (ts.tv_nsec as u64)
}
}
#[link(name = "pthread")]
extern {}
+#[cfg(target_os = "linux")]
+#[link(name = "rt")]
+extern {}
+
#[cfg(target_os = "win32")]
#[link(name = "ws2_32")]
#[link(name = "psapi")]
pub mod common {
pub mod posix01 {
use libc::types::common::c95::{c_void};
- use libc::types::os::arch::c95::{c_char, c_ulong, size_t};
+ use libc::types::os::arch::c95::{c_char, c_ulong, size_t,
+ time_t, suseconds_t, c_long};
pub type pthread_t = c_ulong;
__unused4: *c_void,
__unused5: *c_void,
}
+
+ pub struct timeval {
+ tv_sec: time_t,
+ tv_usec: suseconds_t,
+ }
+
+ pub struct timespec {
+ tv_sec: time_t,
+ tv_nsec: c_long,
+ }
+
+ pub enum timezone {}
}
pub mod bsd44 {
pub type socklen_t = u32;
pub type ptrdiff_t = i32;
pub type clock_t = i32;
pub type time_t = i32;
+ pub type suseconds_t = i32;
pub type wchar_t = i32;
}
pub mod c99 {
pub type ptrdiff_t = i64;
pub type clock_t = i64;
pub type time_t = i64;
+ pub type suseconds_t = i64;
pub type wchar_t = i32;
}
pub mod c99 {
pub mod common {
pub mod posix01 {
use libc::types::common::c95::{c_void};
- use libc::types::os::arch::c95::{c_char, c_int, size_t};
+ use libc::types::os::arch::c95::{c_char, c_int, size_t,
+ time_t, suseconds_t, c_long};
use libc::types::os::arch::c99::{uintptr_t};
pub type pthread_t = uintptr_t;
__unused7: *c_void,
__unused8: *c_void,
}
+
+ pub struct timeval {
+ tv_sec: time_t,
+ tv_usec: suseconds_t,
+ }
+
+ pub struct timespec {
+ tv_sec: time_t,
+ tv_nsec: c_long,
+ }
+
+ pub enum timezone {}
}
pub mod bsd44 {
pub type socklen_t = u32;
pub type ptrdiff_t = i64;
pub type clock_t = i32;
pub type time_t = i64;
+ pub type suseconds_t = i64;
pub type wchar_t = i32;
}
pub mod c99 {
pub mod os {
pub mod common {
pub mod posix01 {
- use libc::types::os::arch::c95::c_short;
+ use libc::types::os::arch::c95::{c_short, time_t, suseconds_t,
+ c_long};
use libc::types::os::arch::extra::{int64, time64_t};
use libc::types::os::arch::posix88::{dev_t, ino_t};
use libc::types::os::arch::posix88::mode_t;
actime: time64_t,
modtime: time64_t,
}
+
+ pub struct timeval {
+ tv_sec: time_t,
+ tv_usec: suseconds_t,
+ }
+
+ pub struct timespec {
+ tv_sec: time_t,
+ tv_nsec: c_long,
+ }
+
+ pub enum timezone {}
}
pub mod bsd44 {
#[cfg(target_arch = "x86_64")]
pub type time_t = i64;
+ #[cfg(target_arch = "x86")]
+ pub type suseconds_t = i32;
+ #[cfg(target_arch = "x86_64")]
+ pub type suseconds_t = i64;
+
pub type wchar_t = u16;
}
}
pub type LPOVERLAPPED = *mut OVERLAPPED;
+
+ pub struct FILETIME {
+ dwLowDateTime: DWORD,
+ dwHighDateTime: DWORD,
+ }
+
+ pub type LPFILETIME = *mut FILETIME;
}
}
}
pub mod os {
pub mod common {
pub mod posix01 {
- use libc::types::common::c95::{c_void};
- use libc::types::os::arch::c95::{c_char, c_int, size_t};
+ use libc::types::common::c95::c_void;
+ use libc::types::os::arch::c95::{c_char, c_int, size_t,
+ time_t, suseconds_t, c_long};
use libc::types::os::arch::c99::{uintptr_t};
pub type pthread_t = uintptr_t;
__unused7: *c_void,
__unused8: *c_void,
}
+
+ pub struct timeval {
+ tv_sec: time_t,
+ tv_usec: suseconds_t,
+ }
+
+ pub struct timespec {
+ tv_sec: time_t,
+ tv_nsec: c_long,
+ }
+
+ pub enum timezone {}
}
pub mod bsd44 {
pub type ptrdiff_t = i32;
pub type clock_t = u32;
pub type time_t = i32;
+ pub type suseconds_t = i32;
pub type wchar_t = i32;
}
pub mod c99 {
pub mod bsd44 {
}
pub mod extra {
+ pub struct mach_timebase_info {
+ numer: u32,
+ denom: u32,
+ }
+
+ pub type mach_timebase_info_data_t = mach_timebase_info;
}
}
pub type ptrdiff_t = i64;
pub type clock_t = u64;
pub type time_t = i64;
+ pub type suseconds_t = i32;
pub type wchar_t = i32;
}
pub mod c99 {
pub mod bsd44 {
}
pub mod extra {
+ pub struct mach_timebase_info {
+ numer: u32,
+ denom: u32,
+ }
+
+ pub type mach_timebase_info_data_t = mach_timebase_info;
}
}
}
pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
pub static PTHREAD_CREATE_DETACHED: c_int = 1;
+
+ pub static CLOCK_REALTIME: c_int = 0;
+ pub static CLOCK_MONOTONIC: c_int = 1;
}
pub mod posix08 {
}
pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
pub static PTHREAD_CREATE_DETACHED: c_int = 1;
+
+ pub static CLOCK_REALTIME: c_int = 0;
+ pub static CLOCK_MONOTONIC: c_int = 4;
}
pub mod posix08 {
}
#[cfg(target_os = "freebsd")]
pub mod bsd44 {
use libc::types::common::c95::{c_void};
- use libc::types::os::arch::c95::{c_char, c_uchar, c_int, c_uint,
- size_t};
+ use libc::types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, size_t};
extern {
pub fn sysctl(name: *c_int,
LPMEMORY_BASIC_INFORMATION,
LPSYSTEM_INFO};
use libc::types::os::arch::extra::{HANDLE, LPHANDLE, LARGE_INTEGER,
- PLARGE_INTEGER};
+ PLARGE_INTEGER, LPFILETIME};
extern "system" {
pub fn GetEnvironmentVariableW(n: LPCWSTR,
lpNewFilePointer: PLARGE_INTEGER,
dwMoveMethod: DWORD) -> BOOL;
pub fn SetEndOfFile(hFile: HANDLE) -> BOOL;
+
+ pub fn GetSystemTimeAsFileTime(
+ lpSystemTimeAsFileTime: LPFILETIME);
+
+ pub fn QueryPerformanceFrequency(
+ lpFrequency: *mut LARGE_INTEGER) -> BOOL;
+ pub fn QueryPerformanceCounter(
+ lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL;
}
}
// On linux librt and libdl are indirect dependencies via rustrt,
// and binutils 2.22+ won't add them automatically
#[cfg(target_os = "linux")]
-#[link(name = "rt")]
#[link(name = "dl")]
#[link(name = "m")]
#[link(name = "pthread")]
#[cfg(target_os = "freebsd")]
#[link(name = "execinfo")]
-#[link(name = "rt")]
#[link(name = "pthread")]
extern {}
}
#endif
-#if defined(__WIN32__)
-void
-rust_get_time(int64_t *sec, int32_t *nsec) {
- FILETIME fileTime;
- GetSystemTimeAsFileTime(&fileTime);
-
- // A FILETIME contains a 64-bit value representing the number of
- // hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z.
- // http://support.microsoft.com/kb/167296/en-us
- ULARGE_INTEGER ul;
- ul.LowPart = fileTime.dwLowDateTime;
- ul.HighPart = fileTime.dwHighDateTime;
- uint64_t ns_since_1601 = ul.QuadPart / 10;
-
- const uint64_t NANOSECONDS_FROM_1601_TO_1970 = 11644473600000000ull;
- uint64_t ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970;
- *sec = ns_since_1970 / 1000000;
- *nsec = (ns_since_1970 % 1000000) * 1000;
-}
-#else
-void
-rust_get_time(int64_t *sec, int32_t *nsec) {
-#ifdef __APPLE__
- struct timeval tv;
- gettimeofday(&tv, NULL);
- *sec = tv.tv_sec;
- *nsec = tv.tv_usec * 1000;
-#else
- struct timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
- *sec = ts.tv_sec;
- *nsec = ts.tv_nsec;
-#endif
-}
-#endif
-
-const int64_t ns_per_s = 1000000000LL;
-
-void
-rust_precise_time_ns(uint64_t *ns) {
-
-#ifdef __APPLE__
- uint64_t time = mach_absolute_time();
- mach_timebase_info_data_t info = {0, 0};
- if (info.denom == 0) {
- mach_timebase_info(&info);
- }
- uint64_t time_nano = time * (info.numer / info.denom);
- *ns = time_nano;
-#elif __WIN32__
- LARGE_INTEGER ticks_per_s;
- BOOL query_result = QueryPerformanceFrequency(&ticks_per_s);
- assert(query_result);
- if (ticks_per_s.QuadPart == 0LL) {
- ticks_per_s.QuadPart = 1LL;
- }
- LARGE_INTEGER ticks;
- query_result = QueryPerformanceCounter(&ticks);
- assert(query_result);
- *ns = (uint64_t)((ticks.QuadPart * ns_per_s) / ticks_per_s.QuadPart);
-#else
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- *ns = (uint64_t)(ts.tv_sec * ns_per_s + ts.tv_nsec);
-#endif
-}
-
typedef struct
{
size_t fill; // in bytes; if zero, heapified