Add support for 'std::time::Instant' in Windows

This commit is contained in:
JOE1994 2020-04-01 20:35:56 -04:00
parent 77a307fe7d
commit 957ec2be10
3 changed files with 53 additions and 21 deletions

View file

@ -24,27 +24,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let result = this.GetEnvironmentVariableW(args[0], args[1], args[2])?;
this.write_scalar(Scalar::from_u32(result), dest)?;
}
"SetEnvironmentVariableW" => {
let result = this.SetEnvironmentVariableW(args[0], args[1])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"GetEnvironmentStringsW" => {
let result = this.GetEnvironmentStringsW()?;
this.write_scalar(result, dest)?;
}
"FreeEnvironmentStringsW" => {
let result = this.FreeEnvironmentStringsW(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"GetCurrentDirectoryW" => {
let result = this.GetCurrentDirectoryW(args[0], args[1])?;
this.write_scalar(Scalar::from_u32(result), dest)?;
}
"SetCurrentDirectoryW" => {
let result = this.SetCurrentDirectoryW(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -171,6 +166,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
"GetSystemTimeAsFileTime" => {
this.GetSystemTimeAsFileTime(args[0])?;
}
"QueryPerformanceCounter" => {
let result = this.QueryPerformanceCounter(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"QueryPerformanceFrequency" => {
let result = this.QueryPerformanceFrequency(args[0])?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
// Miscellaneous
"SystemFunction036" => {

View file

@ -117,6 +117,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Ok(())
}
#[allow(non_snake_case)]
fn QueryPerformanceCounter(&mut self, lpPerformanceCount_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.assert_target_os("windows", "QueryPerformanceCounter");
this.check_no_isolation("QueryPerformanceCounter")?;
// QPC uses a hardware counter as its basis.
// Miri will assume that the machine's hardware counter has a resolution of 1 nanosecond.
let duration = Instant::now().duration_since(this.machine.time_anchor);
let qpc = i64::try_from(duration.as_nanos())
.map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported"))?;
this.write_scalar(Scalar::from_i64(qpc), this.deref_operand(lpPerformanceCount_op)?.into())?;
Ok(-1) // return non-zero on success
}
#[allow(non_snake_case)]
fn QueryPerformanceFrequency(&mut self, lpFrequency_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.assert_target_os("windows", "QueryPerformanceFrequency");
this.check_no_isolation("QueryPerformanceFrequency")?;
// Retrieves the frequency of the hardware performance counter.
// The frequency of the performance counter is fixed at system boot and
// is consistent across all processors.
// Miri will assume that the frequency of
// the machine's hardware performance counter is 1 GHz ( = 1 x 10^9 Hz).
this.write_scalar(Scalar::from_i64(1_000_000_000), this.deref_operand(lpFrequency_op)?.into())?;
Ok(-1) // Return non-zero on success
}
fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
let this = self.eval_context_ref();

View file

@ -19,22 +19,19 @@ fn main() {
assert!(2020 <= year && year < 2100);
// Check `Instant`.
#[cfg(not(windows))] // `Instant` shims not yet implemented on Windows
{
let now1 = Instant::now();
// Do some work to make time pass.
for _ in 0..10 { drop(vec![42]); }
let now2 = Instant::now();
assert!(now2 > now1);
let now1 = Instant::now();
// Do some work to make time pass.
for _ in 0..10 { drop(vec![42]); }
let now2 = Instant::now();
assert!(now2 > now1);
#[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
{
let diff = now2.duration_since(now1);
assert_eq!(now1 + diff, now2);
assert_eq!(now2 - diff, now1);
// Sanity-check the difference we got.
assert!(diff.as_micros() > 1);
assert!(diff.as_micros() < 1_000_000);
}
#[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
{
let diff = now2.duration_since(now1);
assert_eq!(now1 + diff, now2);
assert_eq!(now2 - diff, now1);
// Sanity-check the difference we got.
assert!(diff.as_micros() > 1);
assert!(diff.as_micros() < 1_000_000);
}
}