/**************************************************************************** DESCRIPTION: Returns the speed of the processor in MHz. HEADER: cpuinfo.h PARAMETERS: accurate - True of the speed should be measured accurately RETURNS: Processor speed in MHz. REMARKS: This function returns the speed of the CPU in MHz. Note that if the speed cannot be determined, this function will return 0. If the accurate parameter is set to true, this function will spend longer profiling the speed of the CPU, and will not round the CPU speed that is reported. This is important for highly accurate timing using the Pentium RDTSC instruction, but it does take a lot longer for the profiling to produce accurate results. SEE ALSO: CPU_getProcessorSpeedInHz, CPU_getProcessorType, CPU_haveMMX, CPU_getProcessorName ****************************************************************************/ ulong ZAPI CPU_getProcessorSpeed( ibool accurate) { #if defined(__INTEL__) /* Number of cycles needed to execute a single BSF instruction on i386+ * processors. */ u64 speed64; ulong cpuSpeed; uint i; static ulong intel_cycles[] = { 115,47,43, }; static ulong cyrix_cycles[] = { 38,38,52,52, }; static ulong amd_cycles[] = { 49, }; static ulong known_speeds[] = { 2000,1800,1700,1600,1500,1400,1300,1200,1100,1000,950,900,850,800,750, 700,650,600,550,500,450,433,400,350,333,300,266,233,200,166,150,133, 120,100,90,75,66,60,50,33,20,0, }; if (CPU_haveRDTSC()) { GetRDTSCCpuSpeed(accurate, &speed64); PM_div64_32(speed64, speed64, 1000000); cpuSpeed = PM_getlo32(speed64); } else { int type = CPU_getProcessorType(); int processor = type & CPU_mask; int vendor = type & CPU_familyMask; 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 if (vendor == CPU_AMD) cpuSpeed = GetBSFCpuSpeed(ITERATIONS * amd_cycles[0]); else return 0; } /* Now normalise the results given known processors speeds, if the * speed we measure is within 2MHz of the expected values */ if (!accurate) { for (i = 0; known_speeds[i] != 0; i++) { if (cpuSpeed >= (known_speeds[i]-3) && cpuSpeed <= (known_speeds[i]+3)) { return known_speeds[i]; } } } return cpuSpeed; #else return 0; #endif }
struct FREQ_INFO cpuspeed(int clocks) { ulong cycles; // Clock cycles elapsed // during test ushort processor = wincpuid(); // Family of processor DWORD features = wincpufeatures(); // Features of Processor int manual=0; // Specifies whether the user // manually entered the number of // cycles for the BSF instruction. struct FREQ_INFO cpu_speed; // Return structure for // cpuspeed memset(&cpu_speed, 0x00, sizeof(cpu_speed)); if ( processor & CLONE_MASK ) return cpu_speed; // Check for manual BSF instruction clock count if (clocks <= 0) { cycles = ITERATIONS * processor_cycles[processor]; } else if (0 < clocks && clocks <= MAXCLOCKS) { cycles = ITERATIONS * clocks; manual = 1; // Toggle manual control flag. // Note that this mode will not // work properly with processors // which can process multiple // BSF instructions at a time. // For example, manual mode // will not work on a // PentiumPro(R) } if ( ( features&0x00000010 ) && !(manual) ) { // On processors supporting the Read // Time Stamp opcode, compare elapsed // time on the High-Resolution Counter // with elapsed cycles on the Time // Stamp Register. if ( clocks == 0 ) return GetRDTSCCpuSpeed(); else return GetCmosCpuSpeed(); } else if ( processor >= 3 ) { return GetBSFCpuSpeed(cycles); } return cpu_speed; } // cpuspeed()
/**************************************************************************** DESCRIPTION: Returns the speed of the processor in Hz. HEADER: ztimer.h RETURNS: Accurate processor speed in Hz. REMARKS: This function returns the accurate speed of the CPU in Hz. Note that if the speed cannot be determined, this function will return 0. This function is similar to the CPU_getProcessorSpeed function, except that it attempts to accurately measure the CPU speed in Hz. This is used internally in the Zen Timer libraries to provide accurate real world timing information. This is important for highly accurate timing using the Pentium RDTSC instruction, but it does take a lot longer for the profiling to produce accurate results. SEE ALSO: CPU_getProcessorSpeed, CPU_getProcessorType, CPU_haveMMX, CPU_getProcessorName ****************************************************************************/ ulong ZAPI CPU_getProcessorSpeedInHZ( ibool accurate) { #if defined(__INTEL__) if (CPU_haveRDTSC()) { return GetRDTSCCpuSpeed(accurate); } return CPU_getProcessorSpeed(false) * 1000000; #else return 0; #endif }
/**************************************************************************** DESCRIPTION: Returns the speed of the processor in Hz. HEADER: cpuinfo.h RETURNS: Accurate processor speed in Hz. REMARKS: This function returns the accurate speed of the CPU in Hz. Note that if the speed cannot be determined, this function will return 0. This function is similar to the CPU_getProcessorSpeed function, except that it attempts to accurately measure the CPU speed in Hz. This is used internally in the Zen Timer libraries to provide accurate real world timing information. This is important for highly accurate timing using the Pentium RDTSC instruction, but it does take a lot longer for the profiling to produce accurate results. SEE ALSO: CPU_getProcessorSpeed, CPU_getProcessorType, CPU_haveMMX, CPU_getProcessorName ****************************************************************************/ void ZAPI CPU_getProcessorSpeedInHZ( ibool accurate, CPU_largeInteger *speed) { #if defined(__INTEL__) if (CPU_haveRDTSC()) { u64 speed64; GetRDTSCCpuSpeed(accurate, &speed64); speed->low = PM_getlo32(speed64); speed->high = PM_gethi32(speed64); } speed->low = CPU_getProcessorSpeed(false) * 1000000; speed->high = 0; #else speed->low = 0; speed->high = 0; #endif }