CPU detection work

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



ChangeLog:
- Move performance frequency code to misc/cpu.c
- New function, get_cpu_speed()
- Make MHz registry key and QueryPerformanceFrequency use it
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	4 Jul 2003 18:37:56 -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.@)
  */
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	4 Jul 2003 18:37:57 -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,6 +94,48 @@
 #endif
 }
 
+static LONGLONG get_cpu_speed() {
+    
+#ifdef linux
+    FILE		*fp;
+    char		line[256], *s, *value;
+    double		cpuMHz;
+    
+    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) {
+		    LONGLONG res = (LONGLONG)(cpuMHz * 1000000.0);
+		    
+		    TRACE("frequency retrieved as: %lldHz\n", res);
+		    fclose(fp);		    
+		    return res;
+		}
+	    }
+	}
+	fclose(fp);
+    }
+    ERR("Could not locate CPU speed in /proc/cpuinfo, please report to http://bugs.winehq.com/ with the contents of that file\n");
+    ERR("Defaulting to 1000Mhz\n");
+#endif
+    
+    /* either a fault or we're not on linux */
+    return 1000000000;
+}
+
+
 static BYTE PF[64] = {0,};
 
 static void create_registry_keys( const SYSTEM_INFO *info )
@@ -102,6 +148,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;
@@ -130,7 +177,7 @@
     {
         for (i = 0; i < info->dwNumberOfProcessors; i++)
         {
-            char num[10], id[20];
+	     char num[10], id[20];
 
             attr.RootDirectory = cpu_key;
             sprintf( num, "%d", i );
@@ -138,10 +185,15 @@
             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
             {
                 WCHAR idW[20];
+		 DWORD speed = get_cpu_speed() / 1000;
 
                 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, &speed, sizeof(DWORD) );
                 NtClose( hkey );
             }
             RtlFreeUnicodeString( &nameW );
@@ -151,6 +203,52 @@
     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) );
+	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 = get_cpu_speed() / 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.@]

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux