Skip to content

Commit 957ec2b

Browse files
committed
Add support for 'std::time::Instant' in Windows
1 parent 77a307f commit 957ec2b

File tree

3 files changed

+53
-21
lines changed

3 files changed

+53
-21
lines changed

src/shims/foreign_items/windows.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2424
let result = this.GetEnvironmentVariableW(args[0], args[1], args[2])?;
2525
this.write_scalar(Scalar::from_u32(result), dest)?;
2626
}
27-
2827
"SetEnvironmentVariableW" => {
2928
let result = this.SetEnvironmentVariableW(args[0], args[1])?;
3029
this.write_scalar(Scalar::from_i32(result), dest)?;
3130
}
32-
3331
"GetEnvironmentStringsW" => {
3432
let result = this.GetEnvironmentStringsW()?;
3533
this.write_scalar(result, dest)?;
3634
}
37-
3835
"FreeEnvironmentStringsW" => {
3936
let result = this.FreeEnvironmentStringsW(args[0])?;
4037
this.write_scalar(Scalar::from_i32(result), dest)?;
4138
}
42-
4339
"GetCurrentDirectoryW" => {
4440
let result = this.GetCurrentDirectoryW(args[0], args[1])?;
4541
this.write_scalar(Scalar::from_u32(result), dest)?;
4642
}
47-
4843
"SetCurrentDirectoryW" => {
4944
let result = this.SetCurrentDirectoryW(args[0])?;
5045
this.write_scalar(Scalar::from_i32(result), dest)?;
@@ -171,6 +166,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
171166
"GetSystemTimeAsFileTime" => {
172167
this.GetSystemTimeAsFileTime(args[0])?;
173168
}
169+
"QueryPerformanceCounter" => {
170+
let result = this.QueryPerformanceCounter(args[0])?;
171+
this.write_scalar(Scalar::from_i32(result), dest)?;
172+
}
173+
"QueryPerformanceFrequency" => {
174+
let result = this.QueryPerformanceFrequency(args[0])?;
175+
this.write_scalar(Scalar::from_i32(result), dest)?;
176+
}
174177

175178
// Miscellaneous
176179
"SystemFunction036" => {

src/shims/time.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
117117
Ok(())
118118
}
119119

120+
#[allow(non_snake_case)]
121+
fn QueryPerformanceCounter(&mut self, lpPerformanceCount_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
122+
let this = self.eval_context_mut();
123+
124+
this.assert_target_os("windows", "QueryPerformanceCounter");
125+
this.check_no_isolation("QueryPerformanceCounter")?;
126+
127+
// QPC uses a hardware counter as its basis.
128+
// Miri will assume that the machine's hardware counter has a resolution of 1 nanosecond.
129+
let duration = Instant::now().duration_since(this.machine.time_anchor);
130+
let qpc = i64::try_from(duration.as_nanos())
131+
.map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported"))?;
132+
this.write_scalar(Scalar::from_i64(qpc), this.deref_operand(lpPerformanceCount_op)?.into())?;
133+
Ok(-1) // return non-zero on success
134+
}
135+
136+
#[allow(non_snake_case)]
137+
fn QueryPerformanceFrequency(&mut self, lpFrequency_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
138+
let this = self.eval_context_mut();
139+
140+
this.assert_target_os("windows", "QueryPerformanceFrequency");
141+
this.check_no_isolation("QueryPerformanceFrequency")?;
142+
143+
// Retrieves the frequency of the hardware performance counter.
144+
// The frequency of the performance counter is fixed at system boot and
145+
// is consistent across all processors.
146+
// Miri will assume that the frequency of
147+
// the machine's hardware performance counter is 1 GHz ( = 1 x 10^9 Hz).
148+
this.write_scalar(Scalar::from_i64(1_000_000_000), this.deref_operand(lpFrequency_op)?.into())?;
149+
Ok(-1) // Return non-zero on success
150+
}
151+
120152
fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
121153
let this = self.eval_context_ref();
122154

tests/run-pass/time.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,19 @@ fn main() {
1919
assert!(2020 <= year && year < 2100);
2020

2121
// Check `Instant`.
22-
#[cfg(not(windows))] // `Instant` shims not yet implemented on Windows
23-
{
24-
let now1 = Instant::now();
25-
// Do some work to make time pass.
26-
for _ in 0..10 { drop(vec![42]); }
27-
let now2 = Instant::now();
28-
assert!(now2 > now1);
22+
let now1 = Instant::now();
23+
// Do some work to make time pass.
24+
for _ in 0..10 { drop(vec![42]); }
25+
let now2 = Instant::now();
26+
assert!(now2 > now1);
2927

30-
#[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
31-
{
32-
let diff = now2.duration_since(now1);
33-
assert_eq!(now1 + diff, now2);
34-
assert_eq!(now2 - diff, now1);
35-
// Sanity-check the difference we got.
36-
assert!(diff.as_micros() > 1);
37-
assert!(diff.as_micros() < 1_000_000);
38-
}
28+
#[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
29+
{
30+
let diff = now2.duration_since(now1);
31+
assert_eq!(now1 + diff, now2);
32+
assert_eq!(now2 - diff, now1);
33+
// Sanity-check the difference we got.
34+
assert!(diff.as_micros() > 1);
35+
assert!(diff.as_micros() < 1_000_000);
3936
}
4037
}

0 commit comments

Comments
 (0)