Add support for 'std::time::Instant' in Windows
This commit is contained in:
parent
77a307fe7d
commit
957ec2be10
3 changed files with 53 additions and 21 deletions
|
|
@ -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" => {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue