📄 cpuinfo.c
字号:
{#ifdef __INTEL__ if (_CPU_haveCPUID()) return (_CPU_getCPUIDFeatures() & CPU_HaveMMX) != 0; return false;#else return false;#endif}/****************************************************************************DESCRIPTION:Returns true if the processor supports AMD 3DNow! extensions.HEADER:ztimer.hRETURNS:True if 3DNow! is available, false if not.REMARKS:This function determines if the processor supports the AMD 3DNow! extendedinstruction set.SEE ALSO:CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_haveKNI****************************************************************************/ibool ZAPI CPU_have3DNow(void){#ifdef __INTEL__ if (_CPU_haveCPUID()) return _CPU_have3DNow(); return false;#else return false;#endif}/****************************************************************************DESCRIPTION:Returns true if the processor supports Intel KNI extensions.HEADER:ztimer.hRETURNS:True if Intel KNI is available, false if not.REMARKS:This function determines if the processor supports the Intel KNI extendedinstruction set.SEE ALSO:CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow****************************************************************************/ibool ZAPI CPU_haveKNI(void){#ifdef __INTEL__ /* TODO: This needs to be implemented for the Pentium III */ return false;#else return false;#endif}/****************************************************************************RETURNS:True if the RTSC instruction is available, false if not.REMARKS:This function determines if the processor supports the Intel RDTSCinstruction, for high precision timing. If the processor is not an Intel orIntel clone CPU, this function will always return false.DESCRIPTION:Returns true if the processor supports RDTSC extensions.HEADER:ztimer.hRETURNS:True if RTSC is available, false if not.REMARKS:This function determines if the processor supports the RDTSC instructionfor reading the processor time stamp counter.SEE ALSO:CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow****************************************************************************/ibool ZAPI CPU_haveRDTSC(void){#ifdef __INTEL__ if (_CPU_haveCPUID()) return (_CPU_getCPUIDFeatures() & CPU_HaveRDTSC) != 0; return false;#else return false;#endif}#ifdef __INTEL__#define ITERATIONS 16000#define SAMPLINGS 2#define INNER_LOOPS 500/****************************************************************************REMARKS:If processor does not support time stamp reading, but is at least a 386 orabove, utilize method of timing a loop of BSF instructions which take aknown number of cycles to run on i386(tm), i486(tm), and Pentium(R)processors.****************************************************************************/static ulong GetBSFCpuSpeed( ulong cycles){ CPU_largeInteger t0,t1,count_freq; ulong ticks; /* Microseconds elapsed during test */ ulong current; /* Variable to store time elapsed */ int i,j,iPriority; ulong lowest = (ulong)-1; iPriority = SetMaxThreadPriority(); GetCounterFrequency(&count_freq); for (i = 0; i < SAMPLINGS; i++) { GetCounter(&t0); for (j = 0; j < INNER_LOOPS; j++) _CPU_runBSFLoop(ITERATIONS); GetCounter(&t1); current = t1.low - t0.low; if (current < lowest) lowest = current; } RestoreThreadPriority(iPriority); /* Compute frequency */ ticks = (ulong)((lowest * 1000000.0) / (float)(count_freq.low)); if ((ticks % count_freq.low) > (count_freq.low/2)) ticks++; /* Round up if necessary */ if (ticks == 0) return 0; return ((cycles*INNER_LOOPS)/ticks);}/****************************************************************************REMARKS:Utility function to return the absolute value of a number****************************************************************************/static long _abs(long a){ return (a >= 0 ? a : -a);}#define TOLERANCE 1/****************************************************************************REMARKS:On processors supporting the Read Time Stamp opcode, compare elapsedtime on the High-Resolution Counter with elapsed cycles on the TimeStamp Register.The inner loop runs up to 20 times oruntil the average of the previousthree calculated frequencies is within 1 MHz of each of the individualcalculated frequencies. This resampling increases the accuracy of theresults since outside factors could affect this calculation.****************************************************************************/static ulong GetRDTSCCpuSpeed(void){ CPU_largeInteger t0,t1,count_freq; ulong freq=0; /* Most current frequ. calculation */ ulong freq2=0; /* 2nd most current frequ. calc. */ ulong freq3; /* 3rd most current frequ. calc. */ ulong total; /* Sum of previous three frequency calculations */ int tries=0; /* Number of times a calculation has been made */ ulong total_cycles=0, cycles; /* Clock cycles elapsed during test */ ulong stamp0, stamp1; /* Time Stamp Variable for beginning and end of test */ ulong total_ticks=0, ticks; /* Microseconds elapsed during test */ int iPriority; iPriority = SetMaxThreadPriority(); GetCounterFrequency(&count_freq); do { tries++; /* Increment number of times sampled */ freq3 = freq2; /* Shift frequencies back */ freq2 = freq; /* Loop until 100 ticks have passed since last read of hi-res * counter. This accounts for overhead later. */ GetCounter(&t0); t1.low = t0.low; t1.high = t0.high; while ((t1.low - t0.low) < 100) { GetCounter(&t1); stamp0 = _CPU_quickRDTSC(); } /* Loop until 30000 ticks have passed since last read of hi-res counter. * This allows for elapsed time for sampling. For a hi-res frequency * of 1Mhz, this is about 0.03 of a second. The frequency reported * by the OS dependent code should be tuned to provide a good * sample period depending on the accuracy of the OS timers (ie: * if the accuracy is lower, lower the frequency to spend more time * in the inner loop to get better accuracy). */ t0.low = t1.low; t0.high = t1.high; while ((t1.low - t0.low) < 30000) { GetCounter(&t1); stamp1 = _CPU_quickRDTSC(); } /* Find the difference during the timing loop */ cycles = stamp1 - stamp0; ticks = t1.low - t0.low; /* Compute the CPU frequency */ ticks = (ulong)((ticks * 1000000.0) / count_freq.low); total_ticks += ticks; total_cycles += cycles; if ((ticks % count_freq.low) > (count_freq.low/2)) ticks++; /* Round up if necessary */ freq = cycles/ticks; /* Cycles / us = MHz */ if ((cycles % ticks) > (ticks/2)) freq++; /* Round up if necessary */ total = (freq + freq2 + freq3); /* Total last three frequency calculations */ } while ( (tries < 3 ) || ((tries < 20) && ((_abs(3 * freq -total) > (3*TOLERANCE)) || (_abs(3 * freq2-total) > (3*TOLERANCE)) || (_abs(3 * freq3-total) > (3*TOLERANCE))))); RestoreThreadPriority(iPriority); return (total_cycles / total_ticks);}#endif /* __INTEL__ *//****************************************************************************DESCRIPTION:Returns the speed of the processor in Mhz.HEADER:ztimer.hRETURNS:Processor speed in Mhz.REMARKS:This function returns the speed of the CPU in Mhz. Note that if the speedcannot be determined, this function will return 0.SEE ALSO:CPU_getProcessorType, CPU_haveMMX****************************************************************************/ulong ZAPI CPU_getProcessorSpeed(void){#if defined(__INTEL__) /* Number of cycles needed to execute a single BSF instruction on i386+ * processors. */ ulong cpuSpeed; uint i; static ulong intel_cycles[] = { 115,47,43, }; static ulong cyrix_cycles[] = { 38,38,52,52, }; static ulong known_speeds[] = { 650,600,550,500,450,400,350,333,300,266,233,200,166,150,133,120,100,90,75,66,60,50,33,20,0, }; if (CPU_haveRDTSC()) { cpuSpeed = GetRDTSCCpuSpeed(); } else { int processor = CPU_getProcessorType() & CPU_mask; uint vendor = CPU_getProcessorType() & ~CPU_mask; if (vendor == CPU_Intel) cpuSpeed = GetBSFCpuSpeed(ITERATIONS * intel_cycles[processor - CPU_i386]); else if (vendor == CPU_Cyrix) cpuSpeed = GetBSFCpuSpeed(ITERATIONS * cyrix_cycles[processor - CPU_Cyrix6x86]); else return 0; } /* Now normalise the results given known processors speeds, if the * speed we measure is within 2Mhz of the expected values */ for (i = 0; known_speeds[i] != 0; i++) { if (cpuSpeed >= (known_speeds[i]-2) && cpuSpeed <= (known_speeds[i]+2)) { return known_speeds[i]; } } return cpuSpeed;#else return 0;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -