about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2012-02-18 13:13:00 -0800
committerBrian Anderson <andersrb@gmail.com>2012-02-18 13:13:00 -0800
commit9e8fc364b09ff0cd4820d784b3e747c9738ed67b (patch)
treee29cf58c867a59d3c110c81f2167ea5df22cbfc5 /src
parentef6f6285893ca2546d740771b4c8046bfa68f668 (diff)
parent3d202d7eaebd97e2b98a6c6021dd2bb763356d80 (diff)
Merge pull request #1865 from cpeterso/time
Fix Windows system time conversion for get_time()
Diffstat (limited to 'src')
-rw-r--r--src/libstd/time.rs80
-rw-r--r--src/rt/rust_builtin.cpp25
-rw-r--r--src/rt/rustrt.def.in2
3 files changed, 87 insertions, 20 deletions
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 2865666fdc8..aaf94657a8b 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -2,18 +2,25 @@
 Module: time
 */
 
-// FIXME: Document what these functions do
-
 #[abi = "cdecl"]
 native mod rustrt {
     fn get_time(&sec: u32, &usec: u32);
-    fn nano_time(&ns: u64);
+    fn precise_time_ns(&ns: u64);
 }
 
-/* Type: timeval */
+/*
+Type: timeval
+
+A record specifying a time value in seconds and microseconds.
+*/
 type timeval = {sec: u32, usec: u32};
 
-/* Function: get_time */
+/*
+Function: get_time
+
+Returns the current time as a `timeval` containing the seconds and
+microseconds since 1970-01-01T00:00:00Z.
+*/
 fn get_time() -> timeval {
     let sec = 0u32;
     let usec = 0u32;
@@ -21,10 +28,67 @@ fn get_time() -> timeval {
     ret {sec: sec, usec: usec};
 }
 
-/* Function: precise_time_ns */
-fn precise_time_ns() -> u64 { let ns = 0u64; rustrt::nano_time(ns); ret ns; }
+/*
+Function: precise_time_ns
+
+Returns the current value of a high-resolution performance counter
+in nanoseconds since an unspecified epoch.
+*/
+fn precise_time_ns() -> u64 { let ns = 0u64; rustrt::precise_time_ns(ns); ns }
+
+/*
+Function: precise_time_s
 
-/* Function: precise_time_s */
+Returns the current value of a high-resolution performance counter
+in seconds since an unspecified epoch.
+*/
 fn precise_time_s() -> float {
     ret (precise_time_ns() as float) / 1000000000.;
 }
+
+#[cfg(test)]
+mod tests {
+    import task;
+
+    #[test]
+    fn test_get_time() {
+        const some_recent_date: u32 = 1325376000u32; // 2012-01-01T00:00:00Z
+        const some_future_date: u32 = 1577836800u32; // 2020-01-01T00:00:00Z
+
+        let tv1 = get_time();
+        log(debug, "tv1=" + uint::str(tv1.sec as uint) + " sec + "
+                   + uint::str(tv1.usec as uint) + " usec");
+
+        assert tv1.sec > some_recent_date;
+        assert tv1.usec < 1000000u32;
+
+        let tv2 = get_time();
+        log(debug, "tv2=" + uint::str(tv2.sec as uint) + " sec + "
+                   + uint::str(tv2.usec as uint) + " usec");
+
+        assert tv2.sec >= tv1.sec;
+        assert tv2.sec < some_future_date;
+        assert tv2.usec < 1000000u32;
+        if tv2.sec == tv1.sec {
+            assert tv2.usec >= tv1.usec;
+        }
+    }
+
+    #[test]
+    fn test_precise_time() {
+        let s0 = precise_time_s();
+        let ns1 = precise_time_ns();
+
+        log(debug, "s0=" + float::to_str(s0, 9u) + " sec");
+        assert s0 > 0.;
+        let ns0 = (s0 * 1000000000.) as u64;
+        log(debug, "ns0=" + u64::str(ns0) + " ns");
+
+        log(debug, "ns1=" + u64::str(ns1) + " ns");
+        assert ns1 >= ns0;
+
+        let ns2 = precise_time_ns();
+        log(debug, "ns2=" + u64::str(ns2) + " ns");
+        assert ns2 >= ns1;
+    }
+}
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index ecc73204f29..6c0cd5e5fc0 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -393,18 +393,21 @@ rust_ptr_eq(type_desc *t, rust_box *a, rust_box *b) {
 #if defined(__WIN32__)
 extern "C" CDECL void
 get_time(uint32_t *sec, uint32_t *usec) {
-    rust_task *task = rust_task_thread::get_task();
-    SYSTEMTIME systemTime;
     FILETIME fileTime;
-    GetSystemTime(&systemTime);
-    if (!SystemTimeToFileTime(&systemTime, &fileTime)) {
-        task->fail();
-        return;
-    }
+    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;
 
-    // FIXME: This is probably completely wrong.
-    *sec = fileTime.dwHighDateTime;
-    *usec = fileTime.dwLowDateTime;
+    const uint64_t NANOSECONDS_FROM_1601_TO_1970 = 11644473600000000u;
+    uint64_t ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970;
+    *sec = ns_since_1970 / 1000000;
+    *usec = ns_since_1970 % 1000000;
 }
 #else
 extern "C" CDECL void
@@ -417,7 +420,7 @@ get_time(uint32_t *sec, uint32_t *usec) {
 #endif
 
 extern "C" CDECL void
-nano_time(uint64_t *ns) {
+precise_time_ns(uint64_t *ns) {
     timer t;
     *ns = t.time_ns();
 }
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index d4fbc0b90bd..5b62d606917 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -13,10 +13,10 @@ get_port_id
 get_task_id
 get_time
 last_os_error
-nano_time
 new_port
 new_task
 port_recv
+precise_time_ns
 rust_port_select
 rand_free
 rand_new