VirtualBox

Ignore:
Timestamp:
Sep 6, 2007 2:25:36 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
24197
Message:

More statistics. Started implementing the guest side.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxService/VBoxGuest.cpp

    r4524 r4573  
    1818#define _WIN32_WINNT 0x0500
    1919#include <windows.h>
     20#include <psapi.h>
    2021#include "VBoxService.h"
    2122#include "VBoxGuest.h"
     
    3132    const VBOXSERVICEENV *pEnv;
    3233    uint32_t              uStatInterval;
     34    uint32_t              uMemBalloonSize;
     35
     36    uint64_t              ullLastCpuLoad_Idle;
     37    uint64_t              ullLastCpuLoad_Kernel;
     38    uint64_t              ullLastCpuLoad_User;
    3339
    3440    NTSTATUS (WINAPI *pfnNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
     41    void     (WINAPI *pfnGlobalMemoryStatusEx)(LPMEMORYSTATUSEX lpBuffer);
     42    BOOL     (WINAPI *pfnGetPerformanceInfo)(PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb);
    3543} VBOXGUESTCONTEXT;
    3644
     
    4654    dprintf(("VBoxGuestInit\n"));
    4755
    48     gCtx.pEnv          = pEnv;
    49     gCtx.uStatInterval = 0;     /* default */
     56    gCtx.pEnv                   = pEnv;
     57    gCtx.uStatInterval          = 0;     /* default */
     58    gCtx.ullLastCpuLoad_Idle    = 0;
     59    gCtx.ullLastCpuLoad_Kernel  = 0;
     60    gCtx.ullLastCpuLoad_User    = 0;
     61    gCtx.uMemBalloonSize        = 0;
    5062
    5163    VMMDevGetStatisticsChangeRequest req;
     
    6173        dprintf(("VBoxGuestThread: DeviceIoControl failed with %d\n", GetLastError()));
    6274
     75    /* NtQuerySystemInformation might be dropped in future releases, so load it dynamically as per Microsoft's recommendation */
    6376    HMODULE hMod = LoadLibrary("NTDLL.DLL");
    6477    if (hMod)
     
    6881            dprintf(("gCtx.pfnNtQuerySystemInformation = %x\n", gCtx.pfnNtQuerySystemInformation));
    6982        else
     83        {
    7084            dprintf(("NTDLL.NtQuerySystemInformation not found!!\n"));
    71     }
     85            return VERR_NOT_IMPLEMENTED;
     86        }
     87    }
     88
     89    /* GlobalMemoryStatus is win2k and up, so load it dynamically */
     90    hMod = LoadLibrary("KERNEL32.DLL");
     91    if (hMod)
     92    {
     93        *(uintptr_t *)&gCtx.pfnGlobalMemoryStatusEx = (uintptr_t)GetProcAddress(hMod, "GlobalMemoryStatus");
     94        if (gCtx.pfnGlobalMemoryStatusEx)
     95            dprintf(("gCtx.GlobalMemoryStatus= %x\n", gCtx.pfnGlobalMemoryStatusEx));
     96        else
     97        {
     98            /** @todo now fails in NT4; do we care? */
     99            dprintf(("KERNEL32.GlobalMemoryStatus not found!!\n"));
     100            return VERR_NOT_IMPLEMENTED;
     101        }
     102    }
     103    /* GetPerformanceInfo is xp and up, so load it dynamically */
     104    hMod = LoadLibrary("PSAPI.DLL");
     105    if (hMod)
     106    {
     107        *(uintptr_t *)&gCtx.pfnGetPerformanceInfo = (uintptr_t)GetProcAddress(hMod, "GetPerformanceInfo");
     108        if (gCtx.pfnGetPerformanceInfo)
     109            dprintf(("gCtx.pfnGetPerformanceInfo= %x\n", gCtx.pfnGetPerformanceInfo));
     110        /* failure is not fatal */
     111    }
     112
     113    /* Check balloon size */
     114    DWORD dwMemBalloonSize;
     115    if (DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_CTL_CHECK_BALLOON, NULL, 0, &dwMemBalloonSize, sizeof(dwMemBalloonSize), &cbReturned, NULL))
     116    {
     117        dprintf(("VBoxGuestThread: new balloon size % MB\n", dwMemBalloonSize));
     118        gCtx.uMemBalloonSize = dwMemBalloonSize;
     119    }
     120    else
     121        dprintf(("VBoxGuestThread: DeviceIoControl (balloon) failed with %d\n", GetLastError()));
    72122
    73123    *pfStartThread = true;
     
    81131    dprintf(("VBoxGuestDestroy\n"));
    82132    return;
     133}
     134
     135void VBoxGuestReportStatistics(VBOXGUESTCONTEXT *pCtx)
     136{
     137    SYSTEM_INFO systemInfo;
     138    PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pProcInfo;
     139    MEMORYSTATUSEX memStatus;
     140    VMMDevReportGuestStats req;
     141    uint32_t cbStruct;
     142    DWORD    cbReturned;
     143    HANDLE   gVBoxDriver = pCtx->pEnv->hDriver;
     144
     145    Assert(gCtx.pfnGlobalMemoryStatusEx && gCtx.pfnNtQuerySystemInformation);
     146    if (    !gCtx.pfnGlobalMemoryStatusEx
     147        ||  !gCtx.pfnNtQuerySystemInformation)
     148        return;
     149
     150    vmmdevInitRequest(&req.header, VMMDevReq_ReportGuestStats);
     151
     152    /* Query and report guest statistics */
     153    GetSystemInfo(&systemInfo);
     154
     155    gCtx.pfnGlobalMemoryStatusEx(&memStatus);
     156
     157    req.guestStats.u32PhysMemTotal      = (uint32_t)(memStatus.ullTotalPhys / systemInfo.dwPageSize);
     158    req.guestStats.u32PhysMemAvail      = (uint32_t)(memStatus.ullAvailPhys / systemInfo.dwPageSize);
     159    req.guestStats.u32PageFileSize      = (uint32_t)(memStatus.ullTotalPageFile / systemInfo.dwPageSize);
     160    req.guestStats.u32MemoryLoad        = memStatus.dwMemoryLoad;
     161    req.guestStats.u32PhysMemBalloon    = pCtx->uMemBalloonSize;    /* in megabytes already */
     162    req.guestStats.u32StatCaps          = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_PAGE_FILE_SIZE | VBOX_GUEST_STAT_MEMORY_LOAD | VBOX_GUEST_STAT_PHYS_MEM_BALLOON;
     163
     164    if (gCtx.pfnGetPerformanceInfo)
     165    {
     166        PERFORMANCE_INFORMATION perfInfo;
     167
     168        if (gCtx.pfnGetPerformanceInfo(&perfInfo, sizeof(perfInfo)))
     169        {
     170            req.guestStats.u32Processes         = perfInfo.ProcessCount;
     171            req.guestStats.u32Threads           = perfInfo.ThreadCount;
     172            req.guestStats.u32MemCommitTotal    = perfInfo.CommitTotal;     /* already in pages */
     173            req.guestStats.u32MemKernelTotal    = perfInfo.KernelTotal;     /* already in pages */
     174            req.guestStats.u32MemKernelPaged    = perfInfo.KernelPaged;     /* already in pages */
     175            req.guestStats.u32MemKernelNonPaged = perfInfo.KernelNonpaged;  /* already in pages */
     176            req.guestStats.u32MemSystemCache    = perfInfo.SystemCache;     /* already in pages */
     177            req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PROCESSES | VBOX_GUEST_STAT_THREADS | VBOX_GUEST_STAT_MEM_COMMIT_TOTAL | VBOX_GUEST_STAT_MEM_KERNEL_TOTAL | VBOX_GUEST_STAT_MEM_KERNEL_PAGED | VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED | VBOX_GUEST_STAT_MEM_SYSTEM_CACHE;
     178        }
     179        else
     180            dprintf(("GetPerformanceInfo failed with %d\n", GetLastError()));
     181    }
     182
     183    /* Query CPU load information */
     184    cbStruct = systemInfo.dwNumberOfProcessors*sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
     185    pProcInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)malloc(cbStruct);
     186    Assert(pProcInfo);
     187    if (!pProcInfo)
     188        return;
     189
     190    /* Unfortunately GetSystemTimes is XP SP1 and up only, so we need to use the semi-undocumented NtQuerySystemInformation */
     191    NTSTATUS rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned);
     192    if (    !rc
     193        &&  cbReturned == cbStruct)
     194    {
     195        if (gCtx.ullLastCpuLoad_Kernel == 0)
     196        {   
     197            /* first time */
     198            gCtx.ullLastCpuLoad_Idle    = pProcInfo->IdleTime.QuadPart;
     199            gCtx.ullLastCpuLoad_Kernel  = pProcInfo->KernelTime.QuadPart;
     200            gCtx.ullLastCpuLoad_User    = pProcInfo->UserTime.QuadPart;
     201
     202            Sleep(250);
     203
     204            rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned);
     205            Assert(!rc);
     206        }
     207
     208        uint64_t deltaIdle    = (pProcInfo->IdleTime.QuadPart - gCtx.ullLastCpuLoad_Idle);
     209        uint64_t deltaKernel  = (pProcInfo->KernelTime.QuadPart - gCtx.ullLastCpuLoad_Kernel);
     210        uint64_t deltaUser    = (pProcInfo->UserTime.QuadPart - gCtx.ullLastCpuLoad_User);
     211        uint64_t ullTotalTime = deltaIdle + deltaKernel + deltaUser;
     212
     213        req.guestStats.u32CpuLoad_Idle      = (uint32_t)(deltaIdle  * 100 / ullTotalTime);
     214        req.guestStats.u32CpuLoad_Kernel    = (uint32_t)(deltaKernel* 100 / ullTotalTime);
     215        req.guestStats.u32CpuLoad_User      = (uint32_t)(deltaUser  * 100 / ullTotalTime);
     216
     217        req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER;
     218
     219        gCtx.ullLastCpuLoad_Idle    = pProcInfo->IdleTime.QuadPart;
     220        gCtx.ullLastCpuLoad_Kernel  = pProcInfo->KernelTime.QuadPart;
     221        gCtx.ullLastCpuLoad_User    = pProcInfo->UserTime.QuadPart;
     222    }
     223
     224    for (uint32_t i=0;i<systemInfo.dwNumberOfProcessors;i++)
     225    {
     226        req.guestStats.u32CpuId = i;
     227
     228        if (DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_VMMREQUEST, &req, req.header.size, &req, req.header.size, &cbReturned, NULL))
     229        {
     230            dprintf(("VBoxGuestThread: new statistics reported successfully!\n"));
     231        }
     232        else
     233            dprintf(("VBoxGuestThread: DeviceIoControl (stats report) failed with %d\n", GetLastError()));
     234    }
     235
     236    free(pProcInfo);
    83237}
    84238
     
    126280            if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST)
    127281            {
    128                 DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_CTL_CHECK_BALLOON, NULL, 0, NULL, 0, NULL, NULL);
     282                DWORD dwMemBalloonSize;
     283                if (DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_CTL_CHECK_BALLOON, NULL, 0, &dwMemBalloonSize, sizeof(dwMemBalloonSize), &cbReturned, NULL))
     284                {
     285                    dprintf(("VBoxGuestThread: new balloon size % MB\n", dwMemBalloonSize));
     286                    pCtx->uMemBalloonSize = dwMemBalloonSize;
     287                }
     288                else
     289                    dprintf(("VBoxGuestThread: DeviceIoControl (balloon) failed with %d\n", GetLastError()));
    129290            }
    130291            if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST)
     
    140301                }
    141302                else
    142                     dprintf(("VBoxGuestThread: DeviceIoControl failed with %d\n", GetLastError()));
    143 
     303                    dprintf(("VBoxGuestThread: DeviceIoControl (stat) failed with %d\n", GetLastError()));
    144304            }
    145305        }
     
    155315            }
    156316        }
     317        /* Report statistics to the host */
    157318        if (    gCtx.uStatInterval
    158319            &&  gCtx.pfnNtQuerySystemInformation)
    159320        {
    160             SYSTEM_INFO systemInfo;
    161 
    162             /* Query and report guest statistics */
    163             GetSystemInfo(&systemInfo);
    164 
    165             //gCtx.pfnNtQuerySystemInformation(
     321            VBoxGuestReportStatistics(pCtx);
    166322        }
    167323    }
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