cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* $Id$ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Check the various time sources on Windows NT.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2009-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * available from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * General Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * of the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * CDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * You may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * terms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Header Files *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <Windows.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/asm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/asm-amd64-x86.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/err.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/string.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/test.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Structures and Typedefs *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef struct _MY_KSYSTEM_TIME
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ULONG LowPart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LONG High1Time;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LONG High2Time;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} MY_KSYSTEM_TIME;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef struct _MY_KUSER_SHARED_DATA
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ULONG TickCountLowDeprecated;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ULONG TickCountMultiplier;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync volatile MY_KSYSTEM_TIME InterruptTime;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync volatile MY_KSYSTEM_TIME SystemTime;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync volatile MY_KSYSTEM_TIME TimeZoneBias;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* The rest is not relevant. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} MY_KUSER_SHARED_DATA;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** The fixed pointer to the user shared data. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define MY_USER_SHARED_DATA ((MY_KUSER_SHARED_DATA *)0x7ffe0000)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Spins until GetTickCount() changes. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void SpinUntilTick(void)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* spin till GetTickCount changes. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync DWORD dwMsTick = GetTickCount();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (GetTickCount() == dwMsTick)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* nothing */;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Delay function that tries to return right after GetTickCount changed. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void DelayMillies(DWORD dwMsStart, DWORD cMillies)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Delay cMillies - 1. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Sleep(cMillies - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (GetTickCount() - dwMsStart < cMillies - 1U)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Sleep(1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync SpinUntilTick();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncint main(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Init, create a test instance and "parse" arguments.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTEST hTest;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTTestInitAndCreate("nttimesources", &hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (argc > 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(hTest, "Syntax error! no arguments expected");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Guess MHz using GetTickCount.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestSub(hTest, "Guess MHz");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync DWORD dwTickStart, dwTickEnd, cMsTicks;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64TscStart, u64TscEnd, cTscTicks;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* get a good start time. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync SpinUntilTick();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dwTickStart = GetTickCount();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMSerializeInstruction();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64TscStart = ASMReadTSC();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } while (GetTickCount() != dwTickStart);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* delay a good while. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync DelayMillies(dwTickStart, 256);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* get a good end time. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dwTickEnd = GetTickCount();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMSerializeInstruction();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64TscEnd = ASMReadTSC();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } while (GetTickCount() != dwTickEnd);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cMsTicks = dwTickEnd - dwTickStart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cTscTicks = u64TscEnd - u64TscStart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Calc an approximate TSC frequency:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cTscTicks / uTscHz = cMsTicks / 1000
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 1 / uTscHz = (cMsTicks / 1000) / cTscTicks
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uTscHz = cTscTicks / (cMsTicks / 1000) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64TscHz = (long double)cTscTicks / ((long double)cMsTicks / 1000.0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( u64TscHz > _1M*3
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && u64TscHz < _1T)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "u64TscHz=%'llu", u64TscHz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(hTest, "u64TscHz=%'llu - out of range", u64TscHz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64TscHz = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Pit GetTickCount, InterruptTime, Performance Counters and TSC against each other.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LARGE_INTEGER PrfHz;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LARGE_INTEGER PrfStart, PrfEnd, cPrfTicks;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LARGE_INTEGER IntStart, IntEnd, cIntTicks;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t i = 0; i < 7; i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestSubF(hTest, "The whole bunch - pass #%u", i + 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!QueryPerformanceFrequency(&PrfHz))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(hTest, "QueryPerformanceFrequency failed (%u)", GetLastError());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* get a good start time. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync SpinUntilTick();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync IntStart.HighPart = MY_USER_SHARED_DATA->InterruptTime.High1Time;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync IntStart.LowPart = MY_USER_SHARED_DATA->InterruptTime.LowPart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dwTickStart = GetTickCount();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!QueryPerformanceCounter(&PrfStart))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(hTest, "QueryPerformanceCounter failed (%u)", GetLastError());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMSerializeInstruction();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64TscStart = ASMReadTSC();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } while ( MY_USER_SHARED_DATA->InterruptTime.High2Time != IntStart.HighPart
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || MY_USER_SHARED_DATA->InterruptTime.LowPart != IntStart.LowPart
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || GetTickCount() != dwTickStart);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* delay a good while. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync DelayMillies(dwTickStart, 256);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* get a good end time. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync IntEnd.HighPart = MY_USER_SHARED_DATA->InterruptTime.High1Time;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync IntEnd.LowPart = MY_USER_SHARED_DATA->InterruptTime.LowPart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dwTickEnd = GetTickCount();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!QueryPerformanceCounter(&PrfEnd))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(hTest, "QueryPerformanceCounter failed (%u)", GetLastError());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMSerializeInstruction();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64TscEnd = ASMReadTSC();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCompilerBarrier();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } while ( MY_USER_SHARED_DATA->InterruptTime.High2Time != IntEnd.HighPart
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || MY_USER_SHARED_DATA->InterruptTime.LowPart != IntEnd.LowPart
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || GetTickCount() != dwTickEnd);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cMsTicks = dwTickEnd - dwTickStart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cTscTicks = u64TscEnd - u64TscStart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cIntTicks.QuadPart = IntEnd.QuadPart - IntStart.QuadPart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cPrfTicks.QuadPart = PrfEnd.QuadPart - PrfStart.QuadPart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Recalc to micro seconds. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64MicroSecMs = (uint64_t)cMsTicks * 1000;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64MicroSecTsc = u64TscHz ? (long double)cTscTicks / u64TscHz * 1000000 : u64MicroSecMs;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64MicroSecInt = cIntTicks.QuadPart / 10; /* 100ns units*/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64MicroSecPrf = (long double)cPrfTicks.QuadPart / PrfHz.QuadPart * 1000000;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* check how much they differ using the millisecond tick count as the standard candle. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, " %9llu / %7lld us - GetTickCount\n", u64MicroSecMs, 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int64_t off = u64MicroSecTsc - u64MicroSecMs;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, " %9llu / %7lld us - TSC\n", u64MicroSecTsc, off);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTEST_CHECK(hTest, RT_ABS(off) < 50000 /*us*/); /* some extra uncertainty with TSC. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync off = u64MicroSecInt - u64MicroSecMs;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, " %9llu / %7lld us - InterruptTime\n", u64MicroSecInt, off);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTEST_CHECK(hTest, RT_ABS(off) < 25000 /*us*/);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync off = u64MicroSecPrf - u64MicroSecMs;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, " %9llu / %7lld us - QueryPerformanceCounter\n", u64MicroSecPrf, off);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTEST_CHECK(hTest, RT_ABS(off) < 25000 /*us*/);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync