// =========================================================================== // (C) 1999 Vienna University of Technology // =========================================================================== // NAME: RDTSCTimer // TYPE: c++ code // PROJECT: Urban Viz/yare (yet another rendering engine) // CONTENT: Very accurate timer for Win32 systems // (uses QueryPerformanceCounter, usually microseconds) // VERSION: 0.1 // =========================================================================== // AUTHORS: mw Michael Wimmer // =========================================================================== // HISTORY: // // 15-jul-99 14:00:00 mw created // =========================================================================== // $Header: /usr/local/cvsyare/cvsyare/src/yareutils/RDTSCTimer.cpp,v 1.2 2005/03/07 17:32:09 wimmer Exp $ // =========================================================================== #ifdef WIN32 #include "RDTSCTimer.h" #include "merror.h" // --------------------------------------------------------------------------- // class RDTSCTimer implementation // --------------------------------------------------------------------------- LARGE_INTEGER RDTSCTimer::frequency = {0,1}; bool RDTSCTimer::isinitialized = false; bool RDTSCTimer::available = false; // this retrieves the timer frequency - will be called by constructor void RDTSCTimer::InitClass(bool verbose) { isinitialized = true; available = true; if (verbose) OUT1(("Calibrating RDTSC-Timer at real-time priority....")); // Increase process class HANDLE hProcess = GetCurrentProcess(); DWORD iPriorityClass = GetPriorityClass(hProcess); ASM_ELSE(iPriorityClass, "couldnt change priority class") SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS); // Increase thread priority HANDLE hThread = GetCurrentThread(); DWORD iPriority = GetThreadPriority(hThread); ASM_ELSE(iPriority != THREAD_PRIORITY_ERROR_RETURN, "couldnt change thread priority") SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); // Measure CPU frequency LARGE_INTEGER PerfFreq; LARGE_INTEGER calStart, calEnd; LARGE_INTEGER perfStart, perfEnd; // warmup RDTSC(calStart); RDTSC(calStart); RDTSC(calStart); ASM_RET( QueryPerformanceFrequency( &PerfFreq ), "QueryPerformanceCounter not available for calibrating!"); QueryPerformanceCounter( &perfStart ); RDTSC(calStart); LARGE_INTEGER endmark; endmark.QuadPart = perfStart.QuadPart + PerfFreq.QuadPart; do { QueryPerformanceCounter( &perfEnd ); } while (perfEnd.QuadPart < endmark.QuadPart); RDTSC(calEnd); // number of Bench cycles counted LARGE_INTEGER perfcounts; perfcounts.QuadPart = perfEnd.QuadPart - perfStart.QuadPart; // number of RDTSC cycles counted LARGE_INTEGER calcounts; calcounts.QuadPart = calEnd.QuadPart - calStart.QuadPart; // note: this might overflow if processor is over 6GHz: unsigned __int64 temp = calcounts.QuadPart * PerfFreq.QuadPart; frequency.QuadPart = temp / perfcounts.QuadPart; //if (verbose) // OUT1( SV(perfcounts.LowPart)<