Listing 1: stat.h A simple timing class
Listing 1: /****************************************************************** Module : Stat.h - tools to measure overhead of the tracer Written 1998,1999 by Dmitri Leman Purpose: Purpose: NT kernel mode tracer. *****************************************************************/ #ifndef _STAT_H_ #define _STAT_H_ #pragma pack(push,4) //RDTSC instruction loads the current value of //the processor's timestamp counter into the EDX:EAX //OpCode 0x0f31 #define GetProcessorTickCount(p_i64ReturnCounter) __asm { \ __asm push eax \ __asm push edx \ __asm __emit 0fh \ __asm __emit 31h \ __asm mov DWORD PTR p_i64ReturnCounter, EAX \ __asm mov DWORD PTR p_i64ReturnCounter + 4, EDX \ __asm pop eax \ __asm pop edx \ } struct KeepStat { unsigned __int64 m_ui64TotalTimeIn; ULONG m_ulMinTimeIn; ULONG m_ulMaxTimeIn; ULONG m_ulNumberOfCalls; }; struct GetStat { GetStat(KeepStat & p_rKeep) : m_rKeep(p_rKeep) { unsigned __int64 l_ui64TimeStart; GetProcessorTickCount(l_ui64TimeStart); m_ui64TimeStart = l_ui64TimeStart; } void vRecord() { unsigned __int64 l_ui64TimeEnd; GetProcessorTickCount(l_ui64TimeEnd); ULONG l_ulTimeInside = //can keep up to few seconds (ULONG)(l_ui64TimeEnd - m_ui64TimeStart); ULONG l_dwPrev = InterlockedExchangeAdd( ((long*)&m_rKeep.m_ui64TotalTimeIn), l_ulTimeInside); if(l_dwPrev + l_ulTimeInside < l_dwPrev) {//Overflow. It should not happen too often. InterlockedIncrement (((long*)&m_rKeep.m_ui64TotalTimeIn)+1); } InterlockedIncrement((long*)&m_rKeep.m_ulNumberOfCalls); //The following operations are not thread safe. //But we cannot protect them by a critical section. //Thefefore, we may miss a data once in a while if(m_rKeep.m_ulMinTimeIn > l_ulTimeInside) m_rKeep.m_ulMinTimeIn = l_ulTimeInside; if(m_rKeep.m_ulMaxTimeIn < l_ulTimeInside) m_rKeep.m_ulMaxTimeIn = l_ulTimeInside; } unsigned __int64 m_ui64TimeStart; KeepStat & m_rKeep; };//struct GetStat extern KeepStat g_StatEntry, g_StatReturn; #pragma pack(pop) #endif //define _STAT_H_ // End of File