implement the previously mentioned cmdline params
qpc: refactor IsSafe This was SVN commit r5336.
This commit is contained in:
parent
87b0d08c0e
commit
5383eff15c
@ -283,20 +283,27 @@ bool mahaf_Init()
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return true;
|
||||
|
||||
if(wutil_HasCommandLineArgument("-wNoMahaf"))
|
||||
goto fail;
|
||||
|
||||
{
|
||||
char driverPathname[PATH_MAX];
|
||||
GetDriverPathname(driverPathname, ARRAY_SIZE(driverPathname));
|
||||
|
||||
StartDriver(driverPathname);
|
||||
}
|
||||
|
||||
DWORD shareMode = 0;
|
||||
{
|
||||
const DWORD shareMode = 0;
|
||||
hAken = CreateFile("\\\\.\\Aken", GENERIC_READ, shareMode, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if(hAken == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ModuleSetError(&initState);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
ModuleSetError(&initState);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "lib/sysdep/win/win.h"
|
||||
#include "lib/sysdep/win/wcpu.h"
|
||||
#include "lib/sysdep/win/wutil.h" // wutil_argv
|
||||
#include "pit.h" // PIT_FREQ
|
||||
#include "pmt.h" // PMT_FREQ
|
||||
|
||||
@ -39,16 +40,16 @@ void CounterQPC::Shutdown()
|
||||
|
||||
bool CounterQPC::IsSafe() const
|
||||
{
|
||||
// the PIT is entirely safe (even if annoyingly slow to read)
|
||||
if(m_frequency == PIT_FREQ)
|
||||
return true;
|
||||
|
||||
// note: we have separate modules that directly access some of the
|
||||
// counters potentially used by QPC. disabling the redundant counters
|
||||
// would be ugly (increased coupling). instead, we'll make sure our
|
||||
// implementations could (if necessary) coexist with QPC, but it
|
||||
// shouldn't come to that since only one counter is needed/used.
|
||||
|
||||
// the PIT is entirely safe (even if annoyingly slow to read)
|
||||
if(m_frequency == PIT_FREQ)
|
||||
return true;
|
||||
|
||||
// the PMT is generally safe (see discussion in CounterPmt::IsSafe),
|
||||
// but older QPC implementations had problems with 24-bit rollover.
|
||||
// "System clock problem can inflate benchmark scores"
|
||||
@ -57,32 +58,29 @@ bool CounterQPC::IsSafe() const
|
||||
// incorrect values every 4.6 seconds (i.e. 24 bits @ 3.57 MHz) unless
|
||||
// the timer is polled in the meantime. fortunately, this is guaranteed
|
||||
// by our periodic updates (which come at least that often).
|
||||
if(m_frequency == PIT_FREQ)
|
||||
if(m_frequency == PMT_FREQ)
|
||||
return true;
|
||||
|
||||
// two other implementations have been observed: HPET
|
||||
// (on Vista) and RDTSC (on MP HAL).
|
||||
//
|
||||
// - the HPET is reliable but can't easily be recognized since its
|
||||
// frequency is variable (the spec says > 10 MHz; the master 14.318 MHz
|
||||
// oscillator is often used). note: considering frequencies between
|
||||
// 10..100 MHz to be a HPET would be dangerous because it may actually
|
||||
// be faster or RDTSC slower.
|
||||
//
|
||||
// - the TSC implementation has been known to be buggy (even mentioned
|
||||
// in MSDN) and we don't know which systems have been patched. it is
|
||||
// therefore considered unsafe and recognized by comparing frequency
|
||||
// against the CPU clock.
|
||||
|
||||
// QPC frequency matches the CPU clock => it uses RDTSC => unsafe.
|
||||
if(IsSimilarMagnitude(m_frequency, wcpu_ClockFrequency()))
|
||||
return false;
|
||||
// the TSC has been known to be buggy (even mentioned in MSDN). it is
|
||||
// used on MP HAL systems and can be detected by comparing QPF with the
|
||||
// CPU clock. we consider it unsafe unless the user promises (via
|
||||
// command line) that it's patched and thus reliable on their system.
|
||||
bool usesTsc = IsSimilarMagnitude(m_frequency, wcpu_ClockFrequency());
|
||||
// unconfirmed reports indicate QPC sometimes uses 1/3 of the
|
||||
// CPU clock frequency, so check that as well.
|
||||
if(IsSimilarMagnitude(m_frequency, wcpu_ClockFrequency()/3))
|
||||
return false;
|
||||
usesTsc |= IsSimilarMagnitude(m_frequency, wcpu_ClockFrequency()/3);
|
||||
if(usesTsc)
|
||||
{
|
||||
const bool isTscSafe = wutil_HasCommandLineArgument("-wQpcTscSafe");
|
||||
return isTscSafe;
|
||||
}
|
||||
|
||||
// otherwise: it's apparently using the HPET => safe.
|
||||
// the HPET is reliable and used on Vista. it can't easily be recognized
|
||||
// since its frequency is variable (the spec says > 10 MHz; the master
|
||||
// 14.318 MHz oscillator is often used). considering frequencies in
|
||||
// [10, 100 MHz) to be a HPET would be dangerous because it may actually
|
||||
// be faster or RDTSC slower. we have to exclude all other cases and
|
||||
// assume it's a HPET - and thus safe - if we get here.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "counter.h"
|
||||
|
||||
WINIT_REGISTER_EARLY_INIT2(whrt_Init); // whrt -> wtime
|
||||
WINIT_REGISTER_EARLY_INIT2(whrt_Init); // wutil -> whrt -> wtime
|
||||
WINIT_REGISTER_LATE_SHUTDOWN(whrt_Shutdown);
|
||||
|
||||
|
||||
|
@ -145,6 +145,77 @@ LibError LibError_from_win32(DWORD ret, bool warn_if_failed)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// command line
|
||||
|
||||
// copy of GetCommandLine string. will be tokenized and then referenced by
|
||||
// the argv pointers.
|
||||
static char* argvContents;
|
||||
|
||||
int wutil_argc = 0;
|
||||
char** wutil_argv = 0;
|
||||
|
||||
static void ReadCommandLine()
|
||||
{
|
||||
const char* commandLine = GetCommandLine();
|
||||
// (this changes as quotation marks are removed)
|
||||
size_t numChars = strlen(commandLine);
|
||||
argvContents = (char*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, numChars+1);
|
||||
strcpy_s(argvContents, numChars+1, commandLine);
|
||||
|
||||
// first pass: tokenize string and count number of arguments
|
||||
bool ignoreSpace = false;
|
||||
for(size_t i = 0; i < numChars; i++)
|
||||
{
|
||||
switch(argvContents[i])
|
||||
{
|
||||
case '"':
|
||||
ignoreSpace = !ignoreSpace;
|
||||
// strip the " character
|
||||
memmove(argvContents+i, argvContents+i+1, numChars-i);
|
||||
numChars--;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
if(!ignoreSpace)
|
||||
{
|
||||
argvContents[i] = '\0';
|
||||
wutil_argc++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// have argv entries point into the tokenized string
|
||||
wutil_argv = (char**)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, wutil_argc*sizeof(char*));
|
||||
char* nextArg = argvContents;
|
||||
for(int i = 0; i < wutil_argc; i++)
|
||||
{
|
||||
wutil_argv[i] = nextArg;
|
||||
nextArg += strlen(nextArg)+1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void FreeCommandLine()
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, wutil_argv);
|
||||
HeapFree(GetProcessHeap(), 0, argvContents);
|
||||
}
|
||||
|
||||
|
||||
bool wutil_HasCommandLineArgument(const char* arg)
|
||||
{
|
||||
for(int i = 0; i < wutil_argc; i++)
|
||||
{
|
||||
if(!strcmp(wutil_argv[i], arg))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// directories
|
||||
|
||||
@ -363,6 +434,8 @@ static LibError wutil_Init()
|
||||
|
||||
EnableLowFragmentationHeap();
|
||||
|
||||
ReadCommandLine();
|
||||
|
||||
GetDirectories();
|
||||
|
||||
DetectWindowsVersion();
|
||||
@ -376,6 +449,8 @@ static LibError wutil_Init()
|
||||
|
||||
static LibError wutil_Shutdown()
|
||||
{
|
||||
FreeCommandLine();
|
||||
|
||||
FreeUser32Dll();
|
||||
|
||||
ShutdownLocks();
|
||||
|
@ -85,6 +85,16 @@ LibError LibError_from_GLE(bool warn_if_failed = true);
|
||||
extern LibError LibError_from_win32(DWORD ret, bool warn_if_failed = true);
|
||||
|
||||
|
||||
//
|
||||
// command line
|
||||
//
|
||||
|
||||
extern int wutil_argc;
|
||||
extern char** wutil_argv;
|
||||
|
||||
extern bool wutil_HasCommandLineArgument(const char* arg);
|
||||
|
||||
|
||||
//
|
||||
// directories
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user