mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 04:39:45 +00:00
Use the Pentium's rdtsc instruction (if available) to implement
QueryPerformanceCounter.
This commit is contained in:
parent
2859af9060
commit
4570478a6e
@ -518,6 +518,9 @@ typedef struct _SINGLE_LIST_ENTRY {
|
||||
#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 */
|
||||
|
@ -198,6 +198,8 @@ VOID WINAPI GetSystemInfo(
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ DEFAULT_DEBUG_CHANNEL(win32);
|
||||
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 @@ BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)
|
||||
{
|
||||
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 QueryPerformanceCounter(PLARGE_INTEGER counter)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user