From 5383eff15c9c067cd94d51388f9b1feaf5bfba80 Mon Sep 17 00:00:00 2001 From: janwas Date: Sat, 8 Sep 2007 08:09:32 +0000 Subject: [PATCH] implement the previously mentioned cmdline params qpc: refactor IsSafe This was SVN commit r5336. --- source/lib/sysdep/win/mahaf.cpp | 17 +++++-- source/lib/sysdep/win/whrt/qpc.cpp | 48 +++++++++--------- source/lib/sysdep/win/whrt/whrt.cpp | 2 +- source/lib/sysdep/win/wutil.cpp | 75 +++++++++++++++++++++++++++++ source/lib/sysdep/win/wutil.h | 10 ++++ 5 files changed, 121 insertions(+), 31 deletions(-) diff --git a/source/lib/sysdep/win/mahaf.cpp b/source/lib/sysdep/win/mahaf.cpp index 29d51a7359..e31fd08ee9 100644 --- a/source/lib/sysdep/win/mahaf.cpp +++ b/source/lib/sysdep/win/mahaf.cpp @@ -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; } diff --git a/source/lib/sysdep/win/whrt/qpc.cpp b/source/lib/sysdep/win/whrt/qpc.cpp index 0affa3b4eb..9797789571 100644 --- a/source/lib/sysdep/win/whrt/qpc.cpp +++ b/source/lib/sysdep/win/whrt/qpc.cpp @@ -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; } diff --git a/source/lib/sysdep/win/whrt/whrt.cpp b/source/lib/sysdep/win/whrt/whrt.cpp index 5fc81131bf..061596a5a6 100644 --- a/source/lib/sysdep/win/whrt/whrt.cpp +++ b/source/lib/sysdep/win/whrt/whrt.cpp @@ -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); diff --git a/source/lib/sysdep/win/wutil.cpp b/source/lib/sysdep/win/wutil.cpp index 4f8f073cf3..93a550c97a 100644 --- a/source/lib/sysdep/win/wutil.cpp +++ b/source/lib/sysdep/win/wutil.cpp @@ -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(); diff --git a/source/lib/sysdep/win/wutil.h b/source/lib/sysdep/win/wutil.h index 8d6b2388d8..d197e12e15 100644 --- a/source/lib/sysdep/win/wutil.h +++ b/source/lib/sysdep/win/wutil.h @@ -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 //