Like this? Haven't tested extensively... ChangeLog: Merge CPU detection code into misc/cpu.c Add support for Mhz registry key
Index: misc/cpu.c =================================================================== RCS file: /home/wine/wine/misc/cpu.c,v retrieving revision 1.34 diff -u -r1.34 cpu.c --- misc/cpu.c 30 Jun 2003 18:28:08 -0000 1.34 +++ misc/cpu.c 10 Jul 2003 16:57:30 -0000 @@ -36,6 +36,10 @@ #include <string.h> #include <stdio.h> #include <stdlib.h> +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#endif + #define NONAMELESSUNION #define NONAMELESSSTRUCT @@ -90,7 +94,10 @@ #endif } + + static BYTE PF[64] = {0,}; +static double cpuHz = 1000000000; /* default to a 1GHz */ static void create_registry_keys( const SYSTEM_INFO *info ) { @@ -102,6 +109,7 @@ 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 +146,18 @@ if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) { WCHAR idW[20]; + SYSTEM_INFO si; + double cpuMHz = cpuHz / 1000000; + + GetSystemInfo(&si); /* just init the cpu speed global */ 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) ); + + RtlFreeUnicodeString( &valueW ); + RtlInitUnicodeString( &valueW, mhzKeyW); + NtSetValueKey( hkey, &valueW, 0, REG_DWORD, &cpuMHz, sizeof(DWORD) ); NtClose( hkey ); } RtlFreeUnicodeString( &nameW ); @@ -151,6 +167,53 @@ 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__) && 0 + 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; + TRACE("returning %lld\n", frequency->QuadPart); + return TRUE; + } +#endif + + frequency->s.LowPart = 1000000; + frequency->s.HighPart = 0; + TRACE("returning %lld\n", frequency->QuadPart); + return TRUE; +} + /*********************************************************************** * GetSystemInfo [KERNEL32.@] @@ -178,7 +241,7 @@ ) { static int cache = 0; static SYSTEM_INFO cachedsi; - + TRACE("si=0x%p\n", si); if (cache) { memcpy(si,&cachedsi,sizeof(*si)); return; @@ -305,6 +368,15 @@ 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")) Index: win32/newfns.c =================================================================== RCS file: /home/wine/wine/win32/newfns.c,v retrieving revision 1.47 diff -u -r1.47 newfns.c --- win32/newfns.c 22 May 2003 03:41:27 -0000 1.47 +++ win32/newfns.c 10 Jul 2003 16:57:31 -0000 @@ -45,117 +45,6 @@ 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.@) */