VirtualBox

Changeset 12594 in vbox for trunk/src/VBox/Main/win


Ignore:
Timestamp:
Sep 19, 2008 9:45:17 AM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
36831
Message:

PerfAPI: Fixed lingering VBoxSVC after interrupting VBoxManage with ctrl-C. GetSystemTimes is now linked dynamically with falling back to NtQuerySystemInformation for pre-SP1 XP support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/win/PerformanceWin.cpp

    r12537 r12594  
    2222 */
    2323
    24 /* @todo Replace the following _WIN32_WINNT override with proper diagnostic:
    25 #if (_WIN32_WINNT < 0x0501)
     24#ifndef _WIN32_WINNT
     25#define _WIN32_WINNT 0x0500
     26#else /* !_WIN32_WINNT */
     27#if (_WIN32_WINNT < 0x0500)
    2628#error Win XP or later required!
    27 #endif
    28 */
    29 #ifdef _WIN32_WINNT
    30 #if (_WIN32_WINNT < 0x0501)
    31 #undef _WIN32_WINNT
    32 #define _WIN32_WINNT 0x0501
    33 #endif
    34 #else
    35 #define _WIN32_WINNT 0x0501
    36 #endif
     29#endif /* _WIN32_WINNT < 0x0500 */
     30#endif /* !_WIN32_WINNT */
     31
    3732#include <windows.h>
    38 
     33#include <winternl.h>
    3934#include <psapi.h>
    4035extern "C" {
    4136#include <powrprof.h>
    4237}
     38
    4339#include <iprt/err.h>
    4440#include <iprt/mp.h>
     
    5046#include "Performance.h"
    5147
     48#ifndef NT_ERROR
     49#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3)
     50#endif
     51
    5252namespace pm {
    5353
     
    5555{
    5656public:
     57    CollectorWin();
     58    virtual ~CollectorWin();
    5759    virtual int preCollect(const CollectorHints& hints);
    5860    virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
     
    7678
    7779    VMProcessMap       mProcessStats;
     80
     81    typedef BOOL (WINAPI *PFNGST)(
     82        LPFILETIME lpIdleTime,
     83        LPFILETIME lpKernelTime,
     84        LPFILETIME lpUserTime);
     85    typedef NTSTATUS (WINAPI *PFNNQSI)(
     86        SYSTEM_INFORMATION_CLASS SystemInformationClass,
     87        PVOID SystemInformation,
     88        ULONG SystemInformationLength,
     89        PULONG ReturnLength);
     90
     91    PFNGST  mpfnGetSystemTimes;
     92    PFNNQSI mpfnNtQuerySystemInformation;
     93    HMODULE mhNtDll;
    7894};
    7995
     
    8197{
    8298    return new CollectorWin();
     99}
     100
     101CollectorWin::CollectorWin() : mhNtDll(0)
     102{
     103    mpfnGetSystemTimes = (PFNGST)GetProcAddress(
     104        GetModuleHandle(TEXT("kernel32.dll")),
     105        "GetSystemTimes");
     106    if (!mpfnGetSystemTimes)
     107    {
     108        /* Fall back to deprecated NtQuerySystemInformation */
     109        if (!(mhNtDll = LoadLibrary(TEXT("ntdll.dll"))))
     110        {
     111            LogRel(("Failed to load NTDLL.DLL with error 0x%x. GetSystemTimes() is"
     112                    " not available either. CPU and VM metrics will not be collected.\n",
     113                    GetLastError()));
     114            mpfnNtQuerySystemInformation = 0;
     115        }
     116        else if (!(mpfnNtQuerySystemInformation = (PFNNQSI)GetProcAddress(mhNtDll,
     117            "NtQuerySystemInformation")))
     118        {
     119            LogRel(("Neither GetSystemTimes() nor NtQuerySystemInformation() is"
     120                    " not available. CPU and VM metrics will not be collected.\n"));
     121            mpfnNtQuerySystemInformation = 0;
     122        }
     123    }
     124}
     125
     126CollectorWin::~CollectorWin()
     127{
     128    if (mhNtDll)
     129        FreeLibrary(mhNtDll);
    83130}
    84131
     
    158205}
    159206
     207typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
     208{
     209    LARGE_INTEGER IdleTime;
     210    LARGE_INTEGER KernelTime;
     211    LARGE_INTEGER UserTime;
     212    LARGE_INTEGER Reserved1[2];
     213    ULONG Reserved2;
     214} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
     215
    160216int CollectorWin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
    161217{
     
    164220    FILETIME ftIdle, ftKernel, ftUser;
    165221
    166     if (!GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
    167     {
    168         DWORD dwError = GetLastError();
    169         Log (("GetSystemTimes() -> 0x%x\n", dwError));
    170         return RTErrConvertFromWin32(dwError);
    171     }
    172 
    173     *user   = FILETTIME_TO_100NS(ftUser);
    174     *idle   = FILETTIME_TO_100NS(ftIdle);
    175     *kernel = FILETTIME_TO_100NS(ftKernel) - *idle;
     222    if (mpfnGetSystemTimes)
     223    {
     224        if (!mpfnGetSystemTimes(&ftIdle, &ftKernel, &ftUser))
     225        {
     226            DWORD dwError = GetLastError();
     227            Log (("GetSystemTimes() -> 0x%x\n", dwError));
     228            return RTErrConvertFromWin32(dwError);
     229        }
     230   
     231        *user   = FILETTIME_TO_100NS(ftUser);
     232        *idle   = FILETTIME_TO_100NS(ftIdle);
     233        *kernel = FILETTIME_TO_100NS(ftKernel) - *idle;
     234    }
     235    else
     236    {
     237        /* GetSystemTimes is not available, fall back to NtQuerySystemInformation */
     238        if (!mpfnNtQuerySystemInformation)
     239            return VERR_NOT_IMPLEMENTED;
     240
     241        SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION sppi[MAXIMUM_PROCESSORS];
     242        ULONG ulReturned;
     243        NTSTATUS status = mpfnNtQuerySystemInformation(
     244            SystemProcessorPerformanceInformation, &sppi, sizeof(sppi), &ulReturned);
     245        if (NT_ERROR(status))
     246        {
     247            Log(("NtQuerySystemInformation() -> 0x%x\n", status));
     248            return RTErrConvertFromNtStatus(status);
     249        }
     250        /* Sum up values accross all processors */
     251        *user = *kernel = *idle = 0;
     252        for (unsigned i = 0; i < ulReturned / sizeof(sppi[0]); ++i)
     253        {
     254            *idle   += sppi[i].IdleTime.QuadPart;
     255            *kernel += sppi[i].KernelTime.QuadPart - sppi[i].IdleTime.QuadPart;
     256            *user   += sppi[i].UserTime.QuadPart;
     257        }
     258    }
    176259
    177260    LogFlowThisFunc(("user=%lu kernel=%lu idle=%lu\n", *user, *kernel, *idle));
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette