Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

231 lines
6.1 KiB

/*+ 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