Merge CPU detection code into misc/cpu.c.
Add support for Mhz registry key.
This commit is contained in:
parent
af86c99260
commit
69e609d9e5
62
misc/cpu.c
62
misc/cpu.c
|
@ -36,6 +36,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define NONAMELESSUNION
|
#define NONAMELESSUNION
|
||||||
#define NONAMELESSSTRUCT
|
#define NONAMELESSSTRUCT
|
||||||
|
@ -91,6 +95,7 @@ static inline int have_cpuid(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static BYTE PF[64] = {0,};
|
static BYTE PF[64] = {0,};
|
||||||
|
static ULONGLONG cpuHz = 1000000000; /* default to a 1GHz */
|
||||||
|
|
||||||
static void create_registry_keys( const SYSTEM_INFO *info )
|
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 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 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 SysidW[] = {'A','T',' ','c','o','m','p','a','t','i','b','l','e',0};
|
||||||
|
static const WCHAR mhzKeyW[] = {'~','M','H','z',0};
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
HKEY hkey, system_key, cpu_key;
|
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 ))
|
if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
|
||||||
{
|
{
|
||||||
WCHAR idW[20];
|
WCHAR idW[20];
|
||||||
|
DWORD cpuMHz = cpuHz / 1000000;
|
||||||
|
|
||||||
sprintf( id, "CPU %ld", info->dwProcessorType );
|
sprintf( id, "CPU %ld", info->dwProcessorType );
|
||||||
RtlMultiByteToUnicodeN( idW, sizeof(idW), NULL, id, strlen(id)+1 );
|
RtlMultiByteToUnicodeN( idW, sizeof(idW), NULL, id, strlen(id)+1 );
|
||||||
NtSetValueKey( hkey, &valueW, 0, REG_SZ, idW, (strlenW(idW)+1)*sizeof(WCHAR) );
|
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 );
|
NtClose( hkey );
|
||||||
}
|
}
|
||||||
RtlFreeUnicodeString( &nameW );
|
RtlFreeUnicodeString( &nameW );
|
||||||
|
@ -151,6 +161,49 @@ static void create_registry_keys( const SYSTEM_INFO *info )
|
||||||
NtClose( system_key );
|
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.@]
|
* GetSystemInfo [KERNEL32.@]
|
||||||
|
@ -179,6 +232,7 @@ VOID WINAPI GetSystemInfo(
|
||||||
static int cache = 0;
|
static int cache = 0;
|
||||||
static SYSTEM_INFO cachedsi;
|
static SYSTEM_INFO cachedsi;
|
||||||
|
|
||||||
|
TRACE("si=0x%p\n", si);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
memcpy(si,&cachedsi,sizeof(*si));
|
memcpy(si,&cachedsi,sizeof(*si));
|
||||||
return;
|
return;
|
||||||
|
@ -306,6 +360,14 @@ VOID WINAPI GetSystemInfo(
|
||||||
if (sscanf(value,"%d",&x))
|
if (sscanf(value,"%d",&x))
|
||||||
cachedsi.wProcessorRevision = 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")) ||
|
if ( !strncasecmp(line,"flags",strlen("flags")) ||
|
||||||
!strncasecmp(line,"features",strlen("features"))
|
!strncasecmp(line,"features",strlen("features"))
|
||||||
) {
|
) {
|
||||||
|
|
111
win32/newfns.c
111
win32/newfns.c
|
@ -45,117 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win32);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(debug);
|
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.@)
|
* FlushInstructionCache (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue