VBoxServiceStats.cpp revision edef0eb9023260495fd67751464fae912a3114cd
6a67d144095c31bbafed93cec1619590157335eajvergara * VBoxStats - Guest statistics notification
6a67d144095c31bbafed93cec1619590157335eajvergara * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * This file is part of VirtualBox Open Source Edition (OSE), as
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * available from http://www.virtualbox.org. This file is free software;
6a67d144095c31bbafed93cec1619590157335eajvergara * you can redistribute it and/or modify it under the terms of the GNU
6a67d144095c31bbafed93cec1619590157335eajvergara * General Public License (GPL) as published by the Free Software
6a67d144095c31bbafed93cec1619590157335eajvergara * Foundation, in version 2 as it comes in the "COPYING" file of the
6a67d144095c31bbafed93cec1619590157335eajvergara * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
8cf870d281dc8c242f083d14dfef05f24aa5fceeJnRouvignac * Clara, CA 95054 USA or visit http://www.sun.com if you need
6a67d144095c31bbafed93cec1619590157335eajvergara * additional information or have any questions.
3e6ff045d382a718a951d6305c8910ffc268f893kenneth_suter NTSTATUS (WINAPI *pfnNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
6a67d144095c31bbafed93cec1619590157335eajvergara void (WINAPI *pfnGlobalMemoryStatusEx)(LPMEMORYSTATUSEX lpBuffer);
3e6ff045d382a718a951d6305c8910ffc268f893kenneth_suter BOOL (WINAPI *pfnGetPerformanceInfo)(PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb);
6a67d144095c31bbafed93cec1619590157335eajvergara/*******************************************************************************
6a67d144095c31bbafed93cec1619590157335eajvergara* Global Variables *
5b3741e0620fd2baaa974cecc2c2d953bb7d4fbbkenneth_suter*******************************************************************************/
6a67d144095c31bbafed93cec1619590157335eajvergara/** The semaphore we're blocking on. */
7b6b125d52edabd5b1c9134feef7aeae0e69499ekenneth_suterstatic RTSEMEVENTMULTI g_VMStatEvent = NIL_RTSEMEVENTMULTI;
6a67d144095c31bbafed93cec1619590157335eajvergara/** @copydoc VBOXSERVICE::pfnPreInit */
6a67d144095c31bbafed93cec1619590157335eajvergarastatic DECLCALLBACK(int) VBoxServiceVMStatsPreInit(void)
6a67d144095c31bbafed93cec1619590157335eajvergara/** @copydoc VBOXSERVICE::pfnOption */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic DECLCALLBACK(int) VBoxServiceVMStatsOption(const char **ppszShort, int argc, char **argv, int *pi)
6a67d144095c31bbafed93cec1619590157335eajvergara/** @copydoc VBOXSERVICE::pfnInit */
6a67d144095c31bbafed93cec1619590157335eajvergarastatic DECLCALLBACK(int) VBoxServiceVMStatsInit(void)
6a67d144095c31bbafed93cec1619590157335eajvergara gCtx.cMsStatInterval = 0; /* default; update disabled */
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara rc = VbglR3StatQueryInterval(&gCtx.cMsStatInterval);
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara VBoxServiceVerbose(3, "VBoxStatsInit: new statistics interval %u seconds\n", gCtx.cMsStatInterval);
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara VBoxServiceVerbose(3, "VBoxStatsInit: DeviceIoControl failed with %d\n", rc);
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara /* NtQuerySystemInformation might be dropped in future releases, so load it dynamically as per Microsoft's recommendation */
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara *(uintptr_t *)&gCtx.pfnNtQuerySystemInformation = (uintptr_t)GetProcAddress(hMod, "NtQuerySystemInformation");
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara VBoxServiceVerbose(3, "VBoxStatsInit: gCtx.pfnNtQuerySystemInformation = %x\n", gCtx.pfnNtQuerySystemInformation);
6a67d144095c31bbafed93cec1619590157335eajvergara VBoxServiceError("VBoxStatsInit: NTDLL.NtQuerySystemInformation not found!!\n");
857225469c51bedb8c0566aa7757800cfaac4075kenneth_suter /* GlobalMemoryStatus is win2k and up, so load it dynamically */
6a67d144095c31bbafed93cec1619590157335eajvergara *(uintptr_t *)&gCtx.pfnGlobalMemoryStatusEx = (uintptr_t)GetProcAddress(hMod, "GlobalMemoryStatusEx");
6a67d144095c31bbafed93cec1619590157335eajvergara VBoxServiceVerbose(3, "VBoxStatsInit: gCtx.GlobalMemoryStatusEx = %x\n", gCtx.pfnGlobalMemoryStatusEx);
6a67d144095c31bbafed93cec1619590157335eajvergara /** @todo now fails in NT4; do we care? */
6a67d144095c31bbafed93cec1619590157335eajvergara VBoxServiceError("VBoxStatsInit: KERNEL32.GlobalMemoryStatusEx not found!!\n");
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* GetPerformanceInfo is xp and up, so load it dynamically */
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suter *(uintptr_t *)&gCtx.pfnGetPerformanceInfo = (uintptr_t)GetProcAddress(hMod, "GetPerformanceInfo");
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara VBoxServiceVerbose(3, "VBoxStatsInit: gCtx.pfnGetPerformanceInfo= %x\n", gCtx.pfnGetPerformanceInfo);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* failure is not fatal */
6a67d144095c31bbafed93cec1619590157335eajvergara#endif /* RT_OS_WINDOWS */
6a67d144095c31bbafed93cec1619590157335eajvergara PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pProcInfo;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara Assert(gCtx.pfnGlobalMemoryStatusEx && gCtx.pfnNtQuerySystemInformation);
6a67d144095c31bbafed93cec1619590157335eajvergara /* Query and report guest statistics */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara req.guestStats.u32PageSize = systemInfo.dwPageSize;
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32PhysMemTotal = (uint32_t)(memStatus.ullTotalPhys / systemInfo.dwPageSize);
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32PhysMemAvail = (uint32_t)(memStatus.ullAvailPhys / systemInfo.dwPageSize);
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suter /* The current size of the committed memory limit, in bytes. This is physical memory plus the size of the page file, minus a small overhead. */
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suter req.guestStats.u32PageFileSize = (uint32_t)(memStatus.ullTotalPageFile / systemInfo.dwPageSize) - req.guestStats.u32PhysMemTotal;
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suter req.guestStats.u32MemoryLoad = memStatus.dwMemoryLoad;
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32PhysMemBalloon = VBoxServiceBalloonQueryChunks() * (_1M/systemInfo.dwPageSize); /* was in megabytes */
6a67d144095c31bbafed93cec1619590157335eajvergara 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;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (gCtx.pfnGetPerformanceInfo(&perfInfo, sizeof(perfInfo)))
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara req.guestStats.u32Processes = perfInfo.ProcessCount;
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32MemCommitTotal = perfInfo.CommitTotal; /* already in pages */
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32MemKernelTotal = perfInfo.KernelTotal; /* already in pages */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara req.guestStats.u32MemKernelPaged = perfInfo.KernelPaged; /* already in pages */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara req.guestStats.u32MemKernelNonPaged = perfInfo.KernelNonpaged; /* already in pages */
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32MemSystemCache = perfInfo.SystemCache; /* already in pages */
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_PROCESSES | VBOX_GUEST_STAT_THREADS | VBOX_GUEST_STAT_HANDLES | 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;
6a67d144095c31bbafed93cec1619590157335eajvergara VBoxServiceVerbose(3, "GetPerformanceInfo failed with %d\n", GetLastError());
6a67d144095c31bbafed93cec1619590157335eajvergara /* Query CPU load information */
6a67d144095c31bbafed93cec1619590157335eajvergara cbStruct = systemInfo.dwNumberOfProcessors*sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
6a67d144095c31bbafed93cec1619590157335eajvergara pProcInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)malloc(cbStruct);
6a67d144095c31bbafed93cec1619590157335eajvergara /* Unfortunately GetSystemTimes is XP SP1 and up only, so we need to use the semi-undocumented NtQuerySystemInformation */
6a67d144095c31bbafed93cec1619590157335eajvergara NTSTATUS rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned);
6a67d144095c31bbafed93cec1619590157335eajvergara /* first time */
6a67d144095c31bbafed93cec1619590157335eajvergara gCtx.ullLastCpuLoad_Idle = pProcInfo->IdleTime.QuadPart;
6a67d144095c31bbafed93cec1619590157335eajvergara gCtx.ullLastCpuLoad_Kernel = pProcInfo->KernelTime.QuadPart;
6a67d144095c31bbafed93cec1619590157335eajvergara gCtx.ullLastCpuLoad_User = pProcInfo->UserTime.QuadPart;
6a67d144095c31bbafed93cec1619590157335eajvergara rc = gCtx.pfnNtQuerySystemInformation(SystemProcessorPerformanceInformation, pProcInfo, cbStruct, &cbReturned);
6a67d144095c31bbafed93cec1619590157335eajvergara uint64_t deltaIdle = (pProcInfo->IdleTime.QuadPart - gCtx.ullLastCpuLoad_Idle);
6a67d144095c31bbafed93cec1619590157335eajvergara uint64_t deltaKernel = (pProcInfo->KernelTime.QuadPart - gCtx.ullLastCpuLoad_Kernel);
6a67d144095c31bbafed93cec1619590157335eajvergara uint64_t deltaUser = (pProcInfo->UserTime.QuadPart - gCtx.ullLastCpuLoad_User);
6a67d144095c31bbafed93cec1619590157335eajvergara deltaKernel -= deltaIdle; /* idle time is added to kernel time */
6a67d144095c31bbafed93cec1619590157335eajvergara uint64_t ullTotalTime = deltaIdle + deltaKernel + deltaUser;
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32CpuLoad_Idle = (uint32_t)(deltaIdle * 100 / ullTotalTime);
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32CpuLoad_Kernel = (uint32_t)(deltaKernel* 100 / ullTotalTime);
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32CpuLoad_User = (uint32_t)(deltaUser * 100 / ullTotalTime);
6a67d144095c31bbafed93cec1619590157335eajvergara req.guestStats.u32StatCaps |= VBOX_GUEST_STAT_CPU_LOAD_IDLE | VBOX_GUEST_STAT_CPU_LOAD_KERNEL | VBOX_GUEST_STAT_CPU_LOAD_USER;
6a67d144095c31bbafed93cec1619590157335eajvergara gCtx.ullLastCpuLoad_Idle = pProcInfo->IdleTime.QuadPart;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara gCtx.ullLastCpuLoad_Kernel = pProcInfo->KernelTime.QuadPart;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara gCtx.ullLastCpuLoad_User = pProcInfo->UserTime.QuadPart;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara for (uint32_t i=0; i<systemInfo.dwNumberOfProcessors; i++)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics reported successfully!\n");
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara VBoxServiceVerbose(3, "VBoxStatsReportStatistics: DeviceIoControl (stats report) failed with %d\n", GetLastError());
char *psz;
return rc;
if (*pfShutdown)
if (*pfShutdown)
NULL,
NULL,