// =========================================================================== // (C) 1999 Vienna University of Technology // =========================================================================== // NAME: RDTSCTimer // TYPE: c++ header // PROJECT: Urban Viz/yare (yet another rendering engine) // CONTENT: Very accurate timer for Win32 systems // (uses Pentium clock cycle counter, 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.h,v 1.1 2002/09/24 16:53:56 wimmer Exp $ // =========================================================================== #ifndef NO_PRAGMA_ONCE #pragma once #endif #ifndef _RDTSCTIMER_H #define _RDTSCTIMER_H // use outdated RDTSC instruction with opcodes and register backup, but without cpuid? //#define OLD_RDTSC // use cpuid instruction to serialize execution #define CPUID_RDTSC #ifdef WIN32 #if !(_MSC_VER >= 1200) #define __forceinline inline #endif // we definitely want timers to be inlined! # define PERFTIMER_INLINE __forceinline // the time snapping instruction #ifdef OLDRDTSC #define RDTSC(_VAR) \ _asm { \ _asm push eax \ _asm push edx \ _asm _emit 0Fh \ _asm _emit 31h \ _asm mov _VAR.LowPart, eax \ _asm mov _VAR.HighPart, edx \ _asm pop edx \ _asm pop eax \ } #else #ifdef CPUID_RDTSC #define RDTSC(_VAR) \ _asm { \ _asm xor eax, eax \ _asm cpuid \ _asm rdtsc \ _asm mov _VAR.LowPart, eax \ _asm mov _VAR.HighPart, edx \ } #else #define RDTSC(_VAR) \ _asm { \ _asm rdtsc \ _asm mov _VAR.LowPart, eax \ _asm mov _VAR.HighPart, edx \ } #endif #endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include // for LARGE_INTEGER #endif #define PERFTIMER RDTSCTimer #define TIMEVAL_T LARGE_INTEGER #define TIMEVAL_ZERO(__timval) (__timval).QuadPart = 0; #define TIMEVAL_GET(__timval) { TIMEVAL_T temp; RDTSC(temp); __timval = temp; } #define TIMEVAL_TODOUBLE(__timval) ((double)__timval.QuadPart / (double)frequency.QuadPart) #define TIMEVAL_ASSIGN(__timval1, __timval2) __timval1.QuadPart = __timval2.QuadPart; #define TIMEVAL_ADD(total, end, start) \ if (end.QuadPart > start.QuadPart) \ total.QuadPart += end.QuadPart - start.QuadPart; \ else \ total.QuadPart += MAXLONGLONG - end.QuadPart + start.QuadPart; #include "PerfTimerSkeleton.h" #else #define DUMMY_TIMER #include "PerfTimerSkeleton.h" #undef DUMMY_TIMER #endif #undef PERFTIMER #undef TIMEVAL_ZERO #undef TIMEVAL_TODOUBLE #undef TIMEVAL_ASSIGN // still need these for macro versions //#undef TIMEVAL_GET //#undef TIMEVAL_ADD #endif