QueryPerformanceCounter
James Abbatiello
abbeyj at WPI.EDU
Wed Feb 7 01:19:02 CST 2001
Changelog:
James Abbatiello <jabbey at codeweavers.com>
Use the Pentium's rdtsc instruction (if available) to implement
QueryPerformanceCounter.
--
James Abbatiello
-------------- next part --------------
Index: misc/cpu.c
===================================================================
RCS file: /home/wine/wine/misc/cpu.c,v
retrieving revision 1.17
diff -u -r1.17 cpu.c
--- misc/cpu.c 2000/12/13 20:22:47 1.17
+++ misc/cpu.c 2001/02/07 07:05:26
@@ -198,6 +198,8 @@
PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
if (strstr(value,"mmx"))
PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
+ if (strstr(value,"tsc"))
+ PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
}
}
Index: win32/newfns.c
===================================================================
RCS file: /home/wine/wine/win32/newfns.c,v
retrieving revision 1.27
diff -u -r1.27 newfns.c
--- win32/newfns.c 2000/11/28 22:33:46 1.27
+++ win32/newfns.c 2001/02/07 07:05:26
@@ -7,6 +7,7 @@
/* Misc. new functions - they should be moved into appropriate files
at a later date. */
+#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
@@ -19,6 +20,69 @@
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.564)
*/
@@ -26,9 +90,23 @@
{
struct timeval tv;
- gettimeofday(&tv,NULL);
- counter->s.LowPart = tv.tv_usec+tv.tv_sec*1000000;
- counter->s.HighPart = 0;
+ 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 * 1000000LL;
return TRUE;
}
@@ -37,9 +115,20 @@
*/
BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)
{
- frequency->s.LowPart = 1000000;
- frequency->s.HighPart = 0;
+ 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;
}
/****************************************************************************
Index: include/winnt.h
===================================================================
RCS file: /home/wine/wine/include/winnt.h,v
retrieving revision 1.82
diff -u -r1.82 winnt.h
--- include/winnt.h 2001/01/22 02:17:30 1.82
+++ include/winnt.h 2001/02/07 07:05:27
@@ -514,6 +514,9 @@
#define PF_MMX_INSTRUCTIONS_AVAILABLE 3
#define PF_PPC_MOVEMEM_64BIT_OK 4
#define PF_ALPHA_BYTE_INSTRUCTIONS 5
+#define PF_XMMI_INSTRUCTIONS_AVAILABLE 6
+#define PF_AMD3D_INSTRUCTIONS_AVAILABLE 7
+#define PF_RDTSC_INSTRUCTION_AVAILABLE 8
/* The Win32 register context */
More information about the wine-patches
mailing list