diff --git a/src/Config.h b/src/Config.h index ac2e6609..528d6d82 100644 --- a/src/Config.h +++ b/src/Config.h @@ -30,7 +30,7 @@ #define VER_LAMEXP_MINOR_LO 4 #define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_PATCH 12 -#define VER_LAMEXP_BUILD 834 +#define VER_LAMEXP_BUILD 837 /////////////////////////////////////////////////////////////////////////////// // Tool versions (minimum expected versions!) diff --git a/src/Global.h b/src/Global.h index 2f624ac6..5e800279 100644 --- a/src/Global.h +++ b/src/Global.h @@ -136,6 +136,7 @@ SIZE_T lamexp_dbg_private_bytes(void); //Helper macros #define LAMEXP_DELETE(PTR) if(PTR) { delete PTR; PTR = NULL; } +#define LAMEXP_DELETE_ARRAY(PTR) if(PTR) { delete [] PTR; PTR = NULL; } #define LAMEXP_SAFE_FREE(PTR) if(PTR) { free((void*) PTR); PTR = NULL; } #define LAMEXP_CLOSE(HANDLE) if(HANDLE != NULL && HANDLE != INVALID_HANDLE_VALUE) { CloseHandle(HANDLE); HANDLE = NULL; } #define QWCHAR(STR) reinterpret_cast(STR.utf16()) diff --git a/src/Thread_CPUObserver.cpp b/src/Thread_CPUObserver.cpp index a2a5edb6..e81bedaa 100644 --- a/src/Thread_CPUObserver.cpp +++ b/src/Thread_CPUObserver.cpp @@ -25,7 +25,24 @@ #include #include +//////////////////////////////////////////////////////////// + +typedef enum { SystemProcInfo = 8 } SYSTEM_INFO_CLASS; + +typedef struct +{ + LARGE_INTEGER IdleTime; + LARGE_INTEGER KrnlTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER Reserved[2]; + ULONG Reserved2; +} +SYSTEM_PROC_INFO; + typedef BOOL (WINAPI *GetSystemTimesPtr)(LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); +typedef LONG (WINAPI *NtQuerySystemInformationPtr)(SYSTEM_INFO_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); + +#define IS_OK(X) (((LONG)(X)) == ((LONG)0x00000000L)) //////////////////////////////////////////////////////////// // Constructor & Destructor @@ -74,7 +91,11 @@ ULONGLONG CPUObserverThread::filetime2ulonglong(const void *ftime) void CPUObserverThread::observe(void) { - QLibrary kernel32("kernel32.dll"); + QLibrary kernel32("kernel32.dll"), ntdll("ntdll.dll"); + + ULONG performanceInfoSize = 0; + BYTE *performanceInfoBuffer = NULL; + NtQuerySystemInformationPtr querySysInfo = NULL; GetSystemTimesPtr getSystemTimes = NULL; if(kernel32.load()) @@ -82,7 +103,22 @@ void CPUObserverThread::observe(void) getSystemTimes = reinterpret_cast(kernel32.resolve("GetSystemTimes")); } - if(getSystemTimes != NULL) + if(!getSystemTimes) + { + qWarning("GetSystemTimes() not found, falling back to NtQueryInformationProcess()."); + if(ntdll.load()) + { + querySysInfo = reinterpret_cast(ntdll.resolve("NtQuerySystemInformation")); + if(querySysInfo) + { + querySysInfo(SystemProcInfo, &performanceInfoBuffer, 0, &performanceInfoSize); + if(performanceInfoSize < sizeof(SYSTEM_PROC_INFO)) performanceInfoSize = sizeof(SYSTEM_PROC_INFO); + performanceInfoBuffer = new BYTE[performanceInfoSize]; + } + } + } + + if(getSystemTimes || (querySysInfo && performanceInfoBuffer)) { bool first = true; double previous = -1.0; @@ -96,12 +132,29 @@ void CPUObserverThread::observe(void) forever { - if(getSystemTimes(&idlTime, &sysTime, &usrTime)) + bool ok = false; + + if(getSystemTimes) { - sys[1] = sys[0]; sys[0] = filetime2ulonglong(&sysTime); - usr[1] = usr[0]; usr[0] = filetime2ulonglong(&usrTime); - idl[1] = idl[0]; idl[0] = filetime2ulonglong(&idlTime); + if(ok = getSystemTimes(&idlTime, &sysTime, &usrTime)) + { + sys[1] = sys[0]; sys[0] = filetime2ulonglong(&sysTime); + usr[1] = usr[0]; usr[0] = filetime2ulonglong(&usrTime); + idl[1] = idl[0]; idl[0] = filetime2ulonglong(&idlTime); + } + } + else + { + if(ok = IS_OK(querySysInfo(SystemProcInfo, performanceInfoBuffer, performanceInfoSize, NULL))) + { + sys[1] = sys[0]; sys[0] = reinterpret_cast(performanceInfoBuffer)[0].KrnlTime.QuadPart; + usr[1] = usr[0]; usr[0] = reinterpret_cast(performanceInfoBuffer)[0].UserTime.QuadPart; + idl[1] = idl[0]; idl[0] = reinterpret_cast(performanceInfoBuffer)[0].IdleTime.QuadPart; + } + } + if(ok) + { if(first) { first = false; @@ -132,8 +185,10 @@ void CPUObserverThread::observe(void) } else { - qWarning("GetSystemTimes() ist not available on this system!"); + qWarning("NtQueryInformationProcess() not available, giving up!"); } + + LAMEXP_DELETE_ARRAY(performanceInfoBuffer); } //////////////////////////////////////////////////////////// diff --git a/src/Thread_Initialization.cpp b/src/Thread_Initialization.cpp index b8aff545..6a3aa253 100644 --- a/src/Thread_Initialization.cpp +++ b/src/Thread_Initialization.cpp @@ -650,7 +650,7 @@ void InitializationThread::selfTest(void) qDebug("%02i -> %s", ++n, g_lamexp_tools[i].pcName); } } - if(n != 24) + if(n != 25) { qFatal("Tool count mismatch !!!"); }