From 69e609d9e52b0ca1ee52ce0e4c36c3ddc08d37dc Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Mon, 28 Jul 2003 19:12:33 +0000 Subject: [PATCH] Merge CPU detection code into misc/cpu.c. Add support for Mhz registry key. --- misc/cpu.c | 62 +++++++++++++++++++++++++++ win32/newfns.c | 111 ------------------------------------------------- 2 files changed, 62 insertions(+), 111 deletions(-) diff --git a/misc/cpu.c b/misc/cpu.c index 5b4494ae95e..6413a532545 100644 --- a/misc/cpu.c +++ b/misc/cpu.c @@ -36,6 +36,10 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +# include +#endif + #define NONAMELESSUNION #define NONAMELESSSTRUCT @@ -91,6 +95,7 @@ static inline int have_cpuid(void) } static BYTE PF[64] = {0,}; +static ULONGLONG cpuHz = 1000000000; /* default to a 1GHz */ static void create_registry_keys( const SYSTEM_INFO *info ) { @@ -102,6 +107,7 @@ static void create_registry_keys( const SYSTEM_INFO *info ) static const WCHAR cpuW[] = {'C','e','n','t','r','a','l','P','r','o','c','e','s','s','o','r',0}; static const WCHAR IdentifierW[] = {'I','d','e','n','t','i','f','i','e','r',0}; static const WCHAR SysidW[] = {'A','T',' ','c','o','m','p','a','t','i','b','l','e',0}; + static const WCHAR mhzKeyW[] = {'~','M','H','z',0}; int i; HKEY hkey, system_key, cpu_key; @@ -138,10 +144,14 @@ static void create_registry_keys( const SYSTEM_INFO *info ) if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) { WCHAR idW[20]; + DWORD cpuMHz = cpuHz / 1000000; sprintf( id, "CPU %ld", info->dwProcessorType ); RtlMultiByteToUnicodeN( idW, sizeof(idW), NULL, id, strlen(id)+1 ); NtSetValueKey( hkey, &valueW, 0, REG_SZ, idW, (strlenW(idW)+1)*sizeof(WCHAR) ); + + RtlInitUnicodeString( &valueW, mhzKeyW ); + NtSetValueKey( hkey, &valueW, 0, REG_DWORD, &cpuMHz, sizeof(DWORD) ); NtClose( hkey ); } RtlFreeUnicodeString( &nameW ); @@ -151,6 +161,49 @@ static void create_registry_keys( const SYSTEM_INFO *info ) NtClose( system_key ); } +/**************************************************************************** + * QueryPerformanceCounter (KERNEL32.@) + */ +BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) +{ + struct timeval tv; + +#if defined(__i386__) && defined(__GNUC__) + if (IsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE )) { + /* i586 optimized version */ + __asm__ __volatile__ ( "rdtsc" + : "=a" (counter->s.LowPart), "=d" (counter->s.HighPart) ); + counter->QuadPart = counter->QuadPart / 1000; /* see below */ + return TRUE; + } +#endif + + /* fall back to generic routine (ie, for i386, i486) */ + gettimeofday( &tv, NULL ); + counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000; + return TRUE; +} + + +/**************************************************************************** + * QueryPerformanceFrequency (KERNEL32.@) + */ +BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency) +{ +#if defined(__i386__) && defined(__GNUC__) + if (IsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE )) { + /* The way Windows calculates this value is unclear, however simply using the CPU frequency + gives a value out by approximately a thousand. That can cause some applications to crash, + so we divide here to make our number more similar to the one Windows gives */ + frequency->QuadPart = cpuHz / 1000; + return TRUE; + } +#endif + frequency->s.LowPart = 1000000; + frequency->s.HighPart = 0; + return TRUE; +} + /*********************************************************************** * GetSystemInfo [KERNEL32.@] @@ -179,6 +232,7 @@ VOID WINAPI GetSystemInfo( static int cache = 0; static SYSTEM_INFO cachedsi; + TRACE("si=0x%p\n", si); if (cache) { memcpy(si,&cachedsi,sizeof(*si)); return; @@ -306,6 +360,14 @@ VOID WINAPI GetSystemInfo( if (sscanf(value,"%d",&x)) cachedsi.wProcessorRevision = x; } + if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))) { + double cmz; + if (sscanf( value, "%lf", &cmz ) == 1) { + /* SYSTEMINFO doesn't have a slot for cpu speed, so store in a global */ + cpuHz = cmz * 1000 * 1000; + TRACE("CPU speed read as %lld\n", cpuHz); + } + } if ( !strncasecmp(line,"flags",strlen("flags")) || !strncasecmp(line,"features",strlen("features")) ) { diff --git a/win32/newfns.c b/win32/newfns.c index f3bc247181b..9c3ac40a32b 100644 --- a/win32/newfns.c +++ b/win32/newfns.c @@ -45,117 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win32); WINE_DECLARE_DEBUG_CHANNEL(debug); -static BOOL QUERYPERF_Initialized = 0; -#if defined(__i386__) && defined(__GNUC__) -static BOOL QUERYPERF_RDTSC_Use = 0; -static LONGLONG QUERYPERF_RDTSC_Frequency = 0; -#endif - -static void QUERYPERF_Init(void) -{ -#if defined(__i386__) && defined(__GNUC__) - /* We are running on i386 and compiling on GCC. - * Do a runtime check to see if we have the rdtsc instruction available - */ - FILE *fp; - char line[256], *s, *value; - double cpuMHz; - - TRACE("()\n"); - - if (IsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE )) - { - /* rdtsc is available. However, in order to use it - * we also need to be able to get the processor's - * speed. Currently we do this by reading /proc/cpuinfo - * which makes it Linux-specific. - */ - - TRACE("rdtsc available\n"); - - fp = fopen( "/proc/cpuinfo", "r" ); - if (fp) - { - while(fgets( line, sizeof(line), fp )) - { - /* NOTE: the ':' is the only character we can rely on */ - if (!(value = strchr( line, ':' ))) - continue; - - /* terminate the valuename */ - *value++ = '\0'; - /* skip any leading spaces */ - while (*value == ' ') value++; - if ((s = strchr( value, '\n' ))) - *s = '\0'; - - if (!strncasecmp( line, "cpu MHz", strlen( "cpu MHz" ) )) - { - if (sscanf( value, "%lf", &cpuMHz ) == 1) - { - QUERYPERF_RDTSC_Frequency = (LONGLONG)(cpuMHz * 1000000.0); - QUERYPERF_RDTSC_Use = TRUE; - TRACE("using frequency: %lldHz\n", QUERYPERF_RDTSC_Frequency); - break; - } - } - } - fclose(fp); - } - } -#endif - QUERYPERF_Initialized = TRUE; -} - - -/**************************************************************************** - * QueryPerformanceCounter (KERNEL32.@) - */ -BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) -{ - struct timeval tv; - - if (!QUERYPERF_Initialized) - QUERYPERF_Init(); - -#if defined(__i386__) && defined(__GNUC__) - if (QUERYPERF_RDTSC_Use) - { - /* i586 optimized version */ - __asm__ __volatile__ ( "rdtsc" - : "=a" (counter->s.LowPart), "=d" (counter->s.HighPart) ); - return TRUE; - } - /* fall back to generic routine (ie, for i386, i486) */ -#endif - - /* generic routine */ - gettimeofday( &tv, NULL ); - counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000; - return TRUE; -} - -/**************************************************************************** - * QueryPerformanceFrequency (KERNEL32.@) - */ -BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency) -{ - if (!QUERYPERF_Initialized) - QUERYPERF_Init(); - -#if defined(__i386__) && defined(__GNUC__) - if (QUERYPERF_RDTSC_Use) - { - frequency->QuadPart = QUERYPERF_RDTSC_Frequency; - return TRUE; - } -#endif - - frequency->s.LowPart = 1000000; - frequency->s.HighPart = 0; - return TRUE; -} - /**************************************************************************** * FlushInstructionCache (KERNEL32.@) */