|
|
/*+ pentime.h
* * pentium specific high precision timer functions for 16 or 32 bit apps * (16 bit also needs pentime.asm) * *-======================================================================*/
#ifndef PENTIME_H
#define PENTIME_H
typedef struct { DWORD dwlo; DWORD dwhi; } PENTIMER, NEAR * PPENTIMER;
void FAR PASCAL pentimeInitTimer ( PPENTIMER pptimer);
DWORD FAR PASCAL pentimeGetMicrosecs ( PPENTIMER pptimer);
DWORD FAR PASCAL pentimeGetMicrosecDelta ( PPENTIMER pptimer);
DWORD FAR PASCAL pentimeGetMillisecs ( PPENTIMER pptimer);
struct _pentime_global { DWORD dwTimerKhz; BOOL bActive; PENTIMER base; DWORD dwCpuMhz; DWORD dwCpuKhz; }; extern struct _pentime_global pentime;
//
// macros to make whether to use pentium timers or not a runtime option
//
#ifdef _X86_
#define pentimeGetTime() pentime.bActive ? pentimeGetMillisecs(&pentime.base) : timeGetTime()
#define pentimeGetTicks() pentime.bActive ? pentimeGetMicrosecs(&pentime.base) : timeGetTime()
#define pentimeBegin() pentime.bActive ? (pentimeInitTimer(&pentime.base), 0l) : (void)(pentime.base.dwlo = timeGetTime())
#define pentimeGetTickRate() (pentime.bActive ? (pentime.dwTimerKhz * 1000) : 1000l)
#define pentimeGetDeltaTicks(ppt) pentime.bActive ? pentimeGetMicrosecDelta(ppt) : \
((ppt)->dwhi = (ppt)->dwlo, (ppt)->dwlo = timeGetTime(), (ppt)->dwlo - (ppt)->dwhi)
#else
#define pentimeGetTime() timeGetTime()
#define pentimeGetTicks() timeGetTime()
#define pentimeBegin() (pentime.base.dwlo = timeGetTime())
#define pentimeGetTickRate() (1000l)
#define pentimeGetDeltaTicks(ppt) \
((ppt)->dwhi = (ppt)->dwlo, (ppt)->dwlo = timeGetTime(), (ppt)->dwlo - (ppt)->dwhi)
#endif
#if (defined _INC_PENTIME_CODE_) && (_INC_PENTIME_CODE_ != FALSE)
#undef _INC_PENTIME_CODE_
#define _INC_PENTIME_CODE_ FALSE
struct _pentime_global pentime = {1, 0};
#ifdef _WIN32
#ifdef _X86_
static BYTE opGetP5Ticks[] = { 0x0f, 0x31, // rtdsc
0xc3 // ret
};
static void (WINAPI * GetP5Ticks)() = (LPVOID)opGetP5Ticks;
#pragma warning(disable:4704)
#pragma warning(disable:4035)
void FAR PASCAL pentimeInitTimer ( PPENTIMER pptimer) { GetP5Ticks(); _asm { mov ebx, pptimer mov [ebx], eax mov [ebx+4], edx }; }
DWORD FAR PASCAL pentimeGetCpuTicks ( PPENTIMER pptimer) { GetP5Ticks(); _asm { mov ebx, pptimer sub eax, [ebx] sbb edx, [ebx+4] }; }
DWORD FAR PASCAL pentimeGetMicrosecs ( PPENTIMER pptimer) { GetP5Ticks(); _asm { mov ebx, pptimer sub eax, [ebx] sbb edx, [ebx+4] and edx, 31 // to prevent overflow
mov ecx, pentime.dwCpuMhz div ecx }; }
DWORD WINAPI pentimeGetMicrosecDelta ( PPENTIMER pptimer) { GetP5Ticks(); _asm { mov ebx, pptimer mov ecx, eax sub eax, [ebx] mov [ebx], ecx mov ecx, edx sbb edx, [ebx+4] mov [ebx+4], ecx and edx, 31 mov ecx, pentime.dwCpuMhz div ecx }; }
DWORD FAR PASCAL pentimeGetMillisecs ( PPENTIMER pptimer) { GetP5Ticks(); _asm { mov ebx, pptimer sub eax, [ebx] sbb edx, [ebx+4] and edx, 0x7fff // to prevent overflow
mov ecx, pentime.dwCpuKhz div ecx }; } #endif
void FAR PASCAL pentimeSetMhz ( DWORD dwCpuMhz) { pentime.dwCpuMhz = dwCpuMhz; pentime.dwCpuKhz = dwCpuMhz * 1000; } #else // 16 bit - set mhz is in ASM file
void FAR PASCAL pentimeSetMhz ( DWORD dwCpuMhz);
#endif
void FAR PASCAL pentimeInit ( BOOL bIsPentium, DWORD dwCpuMhz) { if (pentime.bActive = bIsPentium) { pentimeSetMhz (dwCpuMhz); pentime.dwTimerKhz = 1000; } else pentime.dwTimerKhz = 1;
pentimeBegin(); }
#ifdef _WIN32
VOID WINAPI pentimeDetectCPU () { SYSTEM_INFO si; static DWORD MS_INTERVAL = 500; // measure pentium cpu clock for this
// many millisec. the larger this number
// the more accurate our Mhz measurement.
// numbers less than 100 are unlikely
// to be reliable because of the slop
// in GetTickCount
#ifdef _X86_
GetSystemInfo(&si); if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL && si.wProcessorLevel == 5 ) { DWORD dw; PENTIMER qwTicks; DWORD dwTicks;
pentime.bActive = TRUE; pentime.dwTimerKhz = 1000;
timeBeginPeriod(1); dw = timeGetTime (); pentimeInitTimer (&qwTicks);
Sleep(MS_INTERVAL);
dw = timeGetTime() - dw; dwTicks = pentimeGetCpuTicks (&qwTicks); timeEndPeriod(1);
// calculate the CPU Mhz value and Khz value
// to use as millisec and microsec divisors
//
pentime.dwCpuMhz = (dwTicks + dw*500)/dw/1000; pentime.dwCpuKhz = pentime.dwCpuMhz * 1000; } else #endif
{ pentime.bActive = FALSE; pentime.dwTimerKhz = 1; } } #else // win16
VOID WINAPI pentimeDetectCPU () { pentimeInit (FALSE, 33); } #endif
#endif // _INC_PENTIME_CODE_
#endif // PENTIME_H
|