Skip to content

Commit 9e8fc36

Browse files
committed
Merge pull request #1865 from cpeterso/time
Fix Windows system time conversion for get_time()
2 parents ef6f628 + 3d202d7 commit 9e8fc36

File tree

3 files changed

+87
-20
lines changed

3 files changed

+87
-20
lines changed

src/libstd/time.rs

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,93 @@
22
Module: time
33
*/
44

5-
// FIXME: Document what these functions do
6-
75
#[abi = "cdecl"]
86
native mod rustrt {
97
fn get_time(&sec: u32, &usec: u32);
10-
fn nano_time(&ns: u64);
8+
fn precise_time_ns(&ns: u64);
119
}
1210

13-
/* Type: timeval */
11+
/*
12+
Type: timeval
13+
14+
A record specifying a time value in seconds and microseconds.
15+
*/
1416
type timeval = {sec: u32, usec: u32};
1517

16-
/* Function: get_time */
18+
/*
19+
Function: get_time
20+
21+
Returns the current time as a `timeval` containing the seconds and
22+
microseconds since 1970-01-01T00:00:00Z.
23+
*/
1724
fn get_time() -> timeval {
1825
let sec = 0u32;
1926
let usec = 0u32;
2027
rustrt::get_time(sec, usec);
2128
ret {sec: sec, usec: usec};
2229
}
2330

24-
/* Function: precise_time_ns */
25-
fn precise_time_ns() -> u64 { let ns = 0u64; rustrt::nano_time(ns); ret ns; }
31+
/*
32+
Function: precise_time_ns
33+
34+
Returns the current value of a high-resolution performance counter
35+
in nanoseconds since an unspecified epoch.
36+
*/
37+
fn precise_time_ns() -> u64 { let ns = 0u64; rustrt::precise_time_ns(ns); ns }
38+
39+
/*
40+
Function: precise_time_s
2641
27-
/* Function: precise_time_s */
42+
Returns the current value of a high-resolution performance counter
43+
in seconds since an unspecified epoch.
44+
*/
2845
fn precise_time_s() -> float {
2946
ret (precise_time_ns() as float) / 1000000000.;
3047
}
48+
49+
#[cfg(test)]
50+
mod tests {
51+
import task;
52+
53+
#[test]
54+
fn test_get_time() {
55+
const some_recent_date: u32 = 1325376000u32; // 2012-01-01T00:00:00Z
56+
const some_future_date: u32 = 1577836800u32; // 2020-01-01T00:00:00Z
57+
58+
let tv1 = get_time();
59+
log(debug, "tv1=" + uint::str(tv1.sec as uint) + " sec + "
60+
+ uint::str(tv1.usec as uint) + " usec");
61+
62+
assert tv1.sec > some_recent_date;
63+
assert tv1.usec < 1000000u32;
64+
65+
let tv2 = get_time();
66+
log(debug, "tv2=" + uint::str(tv2.sec as uint) + " sec + "
67+
+ uint::str(tv2.usec as uint) + " usec");
68+
69+
assert tv2.sec >= tv1.sec;
70+
assert tv2.sec < some_future_date;
71+
assert tv2.usec < 1000000u32;
72+
if tv2.sec == tv1.sec {
73+
assert tv2.usec >= tv1.usec;
74+
}
75+
}
76+
77+
#[test]
78+
fn test_precise_time() {
79+
let s0 = precise_time_s();
80+
let ns1 = precise_time_ns();
81+
82+
log(debug, "s0=" + float::to_str(s0, 9u) + " sec");
83+
assert s0 > 0.;
84+
let ns0 = (s0 * 1000000000.) as u64;
85+
log(debug, "ns0=" + u64::str(ns0) + " ns");
86+
87+
log(debug, "ns1=" + u64::str(ns1) + " ns");
88+
assert ns1 >= ns0;
89+
90+
let ns2 = precise_time_ns();
91+
log(debug, "ns2=" + u64::str(ns2) + " ns");
92+
assert ns2 >= ns1;
93+
}
94+
}

src/rt/rust_builtin.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -393,18 +393,21 @@ rust_ptr_eq(type_desc *t, rust_box *a, rust_box *b) {
393393
#if defined(__WIN32__)
394394
extern "C" CDECL void
395395
get_time(uint32_t *sec, uint32_t *usec) {
396-
rust_task *task = rust_task_thread::get_task();
397-
SYSTEMTIME systemTime;
398396
FILETIME fileTime;
399-
GetSystemTime(&systemTime);
400-
if (!SystemTimeToFileTime(&systemTime, &fileTime)) {
401-
task->fail();
402-
return;
403-
}
397+
GetSystemTimeAsFileTime(&fileTime);
398+
399+
// A FILETIME contains a 64-bit value representing the number of
400+
// hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z.
401+
// http://support.microsoft.com/kb/167296/en-us
402+
ULARGE_INTEGER ul;
403+
ul.LowPart = fileTime.dwLowDateTime;
404+
ul.HighPart = fileTime.dwHighDateTime;
405+
uint64_t ns_since_1601 = ul.QuadPart / 10;
404406

405-
// FIXME: This is probably completely wrong.
406-
*sec = fileTime.dwHighDateTime;
407-
*usec = fileTime.dwLowDateTime;
407+
const uint64_t NANOSECONDS_FROM_1601_TO_1970 = 11644473600000000u;
408+
uint64_t ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970;
409+
*sec = ns_since_1970 / 1000000;
410+
*usec = ns_since_1970 % 1000000;
408411
}
409412
#else
410413
extern "C" CDECL void
@@ -417,7 +420,7 @@ get_time(uint32_t *sec, uint32_t *usec) {
417420
#endif
418421

419422
extern "C" CDECL void
420-
nano_time(uint64_t *ns) {
423+
precise_time_ns(uint64_t *ns) {
421424
timer t;
422425
*ns = t.time_ns();
423426
}

src/rt/rustrt.def.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ get_port_id
1313
get_task_id
1414
get_time
1515
last_os_error
16-
nano_time
1716
new_port
1817
new_task
1918
port_recv
19+
precise_time_ns
2020
rust_port_select
2121
rand_free
2222
rand_new

0 commit comments

Comments
 (0)