Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

CondorWitte

Querying the CPU clock speed in Win9x

This topic is 6472 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there. This is probably a very simple new-B question: How can I query the CPU clock speed (and presence of MMX) in MS VC++ under Windows 9x? I have looked through the Platform SDK 20 times, but all I find are the GetSystemInfo() and the IsProcessorFeaturePresent() functions. The latter doesn''t work under Win 9x... Any help / hints would be very much appreciated.

Share this post


Link to post
Share on other sites
Advertisement
howdy, I posted a topic about this a while ago, the code that I recieved was this:
        
DWORD GetCpuSpeed()
{
int timeStart = 0;
int timeStop = 0;
unsigned long StartTicks = 0;
unsigned long EndTicks = 0;
unsigned long TotalTicks = 0;
unsigned long cpuSpeed = 0;

timeStart = timeGetTime(); // Get tick edge

for( ; ; )
{
timeStop = timeGetTime();
if ( (timeStop-timeStart) > 1 ) // rollover past 1

{
__asm{
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
_emit 0x0f // CPUID

_emit 0xa2
_emit 0x0f // RTDSC

_emit 0x31
mov [StartTicks], eax // Tick counter starts here

}
break;
}
}

timeStart = timeStop;

for( ; ; )
{
timeStop = timeGetTime();
if ( (timeStop-timeStart) > 1000 ) // one second

{
__asm{
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
_emit 0x0f
_emit 0xa2
_emit 0x0f
_emit 0x31
mov [EndTicks], eax }
break;
}
}

TotalTicks = EndTicks-StartTicks; // total


cpuSpeed = TotalTicks/1000000; // speed


return((DWORD)cpuSpeed);
}

btw, I don't take credit for writing this routine.


JoeMont001@aol.com www.polarisoft.n3.net

Edited by - Julio on September 1, 2000 6:08:04 PM

Share this post


Link to post
Share on other sites
Thanx for the quick response!

This looks good, but is it task-switching-proof?

I don''t know assembler very well; does it treat the _asm blocks as Critical Sections?

I assume there isn''t any Win32-api function call for this...?
;-)

Thanx again, and greetings,

CondorWitte

Share this post


Link to post
Share on other sites
Thats one damn fine bit of code. Self-contained, worked first time. makes a nice change.

credit to the original coder.
(and julio for re-posting, cheers)

Share this post


Link to post
Share on other sites
heh well heres some more code... no _asm is not treated as time critical, but theres also a soultion in here for that =)

I just finnished this yesterday... it has more than just cpu speed... it also determans what version of windows its running under what prosseser its using... 386 486 pentium etc... the speed... MMX 3DNOW ect... and how much memory is in the system... a note on the speed part... theres two version... one for earlier prossessers that don''t suport the Time Stamp Opcode and ones that do...

here you go:
    
///////////////////////////////////////////////Operating System

OSVERSIONINFO osinfo;

osinfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(&osinfo);

if(osinfo.dwPlatformId==VER_PLATFORM_WIN32s)
m_os=MAL_OS_WINS;
if(osinfo.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
m_os=MAL_OS_WIN32_9X;
if(osinfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
m_os=MAL_OS_WIN32_NT;

m_os_version=osinfo.dwMajorVersion<<16;
m_os_version+=osinfo.dwMinorVersion<<8;
m_os_version+=LOWORD(osinfo.dwBuildNumber);

///////////////////////////////////////////////CPU


m_cpu_type=MAL_CPU_TYPE_INTEL;

// _asm _emit 0x0F _asm _emit 0xA2 //CPUID


byte cpu_type=0;
dword dwebx,dwedx,dwecx;

//Intel386 CPU check

//The AC bit (bit 18), is a new bit introduced in the EFLAGS
//register on the Intel486 DX CPU to generate alignment faults.

//This bit can not be set on the Intel386 CPU.



_asm pushfd
_asm pop eax
_asm mov ecx,eax
_asm xor eax,0x40000
_asm push eax
_asm popfd
_asm pushfd
_asm pop eax
_asm xor eax,ecx
_asm mov cpu_type,30
_asm je end_get_cpuid

//Intel486 DX CPU, Intel 487 SX MCP, and Intel486 SX CPU checking
//Checking for the ability to set/clear the ID flag (bit 21) in EFLAGS
//which diferentiates between Pentium (or greater) and the Intel486.
//If the ID flag is set then the CPUID instruction can be used to

//determine the final version of the chip, else it''s a 486


_asm mov cpu_type,40
_asm pushfd
_asm pop eax
_asm mov ecx,eax
_asm or eax,0x200000
_asm push eax
_asm popfd
_asm pushfd
_asm pop eax
_asm xor eax,ecx
_asm je end_get_cpuid

//Otherwise, execute CPUID instruction to determine vendor,
//family, model and stepping.

_asm mov eax,0
_asm _emit 0x0F _asm _emit 0xA2 //CPUID


_asm mov dwebx,ebx
_asm mov dwedx,edx
_asm mov dwecx,ecx

char*ptemp;

ptemp=(char*)&dwebx;
m_cpu_make[0]=ptemp[0];
m_cpu_make[1]=ptemp[1];
m_cpu_make[2]=ptemp[2];
m_cpu_make[3]=ptemp[3];

ptemp=(char*)&dwedx;
m_cpu_make[4]=ptemp[0];
m_cpu_make[5]=ptemp[1];
m_cpu_make[6]=ptemp[2];
m_cpu_make[7]=ptemp[3];

ptemp=(char*)&dwecx;
m_cpu_make[8]=ptemp[0];
m_cpu_make[9]=ptemp[1];
m_cpu_make[10]=ptemp[2];
m_cpu_make[11]=ptemp[3];

m_cpu_make[12]=NULL;

if(!strcmp(m_cpu_make,"GenuineIntel"))
m_cpu_flags|=MAL_CPU_FLAGS_INTEL;

_asm mov eax, 1
_asm _emit 0x0F _asm _emit 0xA2 //CPUID


_asm mov dwedx,edx

_asm push eax

_asm and eax,0F00H
_asm shr eax,8
_asm mov cpu_type,al
cpu_type*=10;

_asm pop eax
_asm push eax

dword model;
_asm mov model,eax

if(((model&0x0610)&&0x0610))//Pentium Pro Check

cpu_type=55;

if(((model&0x1000)&&0x1000))//Pentium OverDrive Check

cpu_type=45;


_asm pop eax


if((dwedx&0x800000))
m_cpu_3d|=MAL_CPU_3D_MMX;

if((dwedx&0x2000000))
m_cpu_3d|=MAL_CPU_3D_SIMD;

if((dwedx&1))
m_cpu_fpu=true;

if((dwedx&0x10))
m_cpu_flags|=MAL_CPU_FLAGS_TSC;

if(!(m_cpu_flags&MAL_CPU_FLAGS_INTEL)){//its AMD Cyrix ect so lets check there extended info

_asm mov eax,0x80000000
_asm _emit 0x0F _asm _emit 0xA2 //CPUID


_asm mov dwedx,edx

if((dwedx&0x800000))
m_cpu_3d|=MAL_CPU_3D_MMX;
if((dwedx&0x400000))
m_cpu_3d|=MAL_CPU_3D_MMXE;
if((dwedx&0x40000000))
m_cpu_3d|=MAL_CPU_3D_E3DNOW;
if((dwedx&0x80000000))
m_cpu_3d|=MAL_CPU_3D_3DNOW;
}

end_get_cpuid:
m_cpu_class=cpu_type;

if(!(m_cpu_flags&MAL_CPU_FLAGS_TSC)){//bsf loop

#define ILIT 4000
static dword processor_cycles[]={00,00,00,115,47,43,38,38,38,38,38,38};
dword cycles=processor_cycles[m_cpu_class/10]*ILIT;

LARGE_INTEGER t0,t1;

dword freq=0;

LARGE_INTEGER count_freq;
dword current=0;
dword lowest=ULONG_MAX;

QueryPerformanceFrequency(&count_freq);

for(int i=0;i<10;i++){
QueryPerformanceCounter(&t0);

_asm mov eax,0x80000000
_asm mov bx,ILIT
loop1: _asm bsf ecx,eax
_asm dec bx
_asm jnz loop1

QueryPerformanceCounter(&t1);
current=(dword)t1.LowPart-(dword)t0.LowPart;
if(current<lowest)
lowest=current;
}
lowest*=100000;
lowest/=count_freq.LowPart/10;
freq=cycles/lowest;

m_cpu_speed=(word)(freq);///1000000);
}else{//Time Stamp

LARGE_INTEGER count_freq,t0,t1;
QueryPerformanceFrequency(&count_freq);

dword stamp0,stamp1;
dword cycles;
dword ticks;
dword freq;

HANDLE hThread = GetCurrentThread();
dword threadp=GetThreadPriority(hThread);
SetThreadPriority(hThread,THREAD_PRIORITY_TIME_CRITICAL);

QueryPerformanceCounter(&t1);
t0.LowPart=t1.LowPart;

while((dword)t1.LowPart-(dword)t0.LowPart<50){
QueryPerformanceCounter(&t1);
_asm _emit 0x0F _asm _emit 0x31//RDTSC

_asm mov stamp0,eax
}

t0.LowPart=t1.LowPart;

while((dword)t1.LowPart-(dword)t0.LowPart<1000){
QueryPerformanceCounter(&t1);
_asm _emit 0x0F _asm _emit 0x31//RDTSC

_asm mov stamp1,eax
}

SetThreadPriority(hThread,threadp);

ticks=(t1.LowPart-t0.LowPart)*100000;
ticks/=(count_freq.LowPart/10 );

cycles=stamp1-stamp0;

freq=cycles/ticks;

m_cpu_speed=(word)freq;
}

///////////////////////////////////////////////Memory


MEMORYSTATUS ms;
ms.dwLength=sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&ms);

m_memory_physical_total=ms.dwTotalPhys;
m_memory_physical_free-ms.dwAvailPhys;
m_memory_virtual_total=ms.dwTotalVirtual;
m_memory_virtual_free=ms.dwAvailVirtual;


not a lot of commments but it shouldn''t be hard to follow =) let me know if you need help =)


Great Milenko

Words Of Wisdom:
"Never Stick A Pretzel In Your Butt It Might Break Off In There."


http://www.crosswinds.net/~milenko
http://www.crosswinds.net/~pirotech

Share this post


Link to post
Share on other sites
Hey Julio I get an unresolved external on
external symbol __imp__timeGetTime@

That shouldn''t happen, right? I am using VC++6. I pasted in the code but I had to redo the spacing. I may have taken out a curly or a line or something .

Could you maybe repost the code with the html code tag so the indexnts are ok?

Thanks.
Lucas

Share this post


Link to post
Share on other sites
hmmm, you''re probably not including a header file. I''m not exactly sure which header file contains that function, but it''s probably either: stdio.h, windows.h. anybody know for sure?
here it is again:

DWORD GetCpuSpeed()
{
int timeStart = 0;
int timeStop = 0;
unsigned long StartTicks = 0;
unsigned long EndTicks = 0;
unsigned long TotalTicks = 0;
unsigned long cpuSpeed = 0;

timeStart = timeGetTime(); // Get tick edge
for( ; ; )
{
timeStop = timeGetTime();
if ( (timeStop-timeStart) > 1 ) // rollover past 1
{
__asm{
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
_emit 0x0f // CPUID
_emit 0xa2
_emit 0x0f // RTDSC
_emit 0x31
mov [StartTicks], eax // Tick counter starts here
}
break;
}
}

timeStart = timeStop;

for( ; ; )
{
timeStop = timeGetTime();
if ( (timeStop-timeStart) > 1000 ) // one second
{
__asm{
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
_emit 0x0f
_emit 0xa2
_emit 0x0f
_emit 0x31
mov [EndTicks], eax }
break;
}
}

TotalTicks = EndTicks-StartTicks; // total

cpuSpeed = TotalTicks/1000000; // speed

return((DWORD)cpuSpeed);
}


JoeMont001@aol.com www.polarisoft.n3.net

Share this post


Link to post
Share on other sites
Hey, thanks.
I was just looking for this information too.

"Now you will see time life music commercials for the rest of your life, no forever! Bwahaha!"
"Nooooooooo!!!!!!!!!!"



Sludge Software
www.sludgesoft.com
Developing a secret of mana style role-playing-game

Share this post


Link to post
Share on other sites
Hey Julio thanx alot, but it didn''t work. I think Gamedev has some weird thing about it where all my copied code is pasted to one line.

As for the error, that is still insistent. I have included all the headers i think it would be in, but it would say undeclared identifier, not unresolved external. Its really doing my head in. Can anyone help?

Lucas

Share this post


Link to post
Share on other sites
I think I got it, Include Winmm.lib in your project and include Mmsystem.h as well.
That's the problem.


The road to success is always under construction

Edited by - Tornado on September 2, 2000 4:05:19 AM

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!