Changeset 4573 in vbox for trunk/src/VBox/Additions/WINNT/VBoxService
- Timestamp:
- Sep 6, 2007 2:25:36 PM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 24197
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxService/VBoxGuest.cpp
r4524 r4573 18 18 #define _WIN32_WINNT 0x0500 19 19 #include <windows.h> 20 #include <psapi.h> 20 21 #include "VBoxService.h" 21 22 #include "VBoxGuest.h" … … 31 32 const VBOXSERVICEENV *pEnv; 32 33 uint32_t uStatInterval; 34 uint32_t uMemBalloonSize; 35 36 uint64_t ullLastCpuLoad_Idle; 37 uint64_t ullLastCpuLoad_Kernel; 38 uint64_t ullLastCpuLoad_User; 33 39 34 40 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); 35 43 } VBOXGUESTCONTEXT; 36 44 … … 46 54 dprintf(("VBoxGuestInit\n")); 47 55 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; 50 62 51 63 VMMDevGetStatisticsChangeRequest req; … … 61 73 dprintf(("VBoxGuestThread: DeviceIoControl failed with %d\n", GetLastError())); 62 74 75 /* NtQuerySystemInformation might be dropped in future releases, so load it dynamically as per Microsoft's recommendation */ 63 76 HMODULE hMod = LoadLibrary("NTDLL.DLL"); 64 77 if (hMod) … … 68 81 dprintf(("gCtx.pfnNtQuerySystemInformation = %x\n", gCtx.pfnNtQuerySystemInformation)); 69 82 else 83 { 70 84 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())); 72 122 73 123 *pfStartThread = true; … … 81 131 dprintf(("VBoxGuestDestroy\n")); 82 132 return; 133 } 134 135 void 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); 83 237 } 84 238 … … 126 280 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST) 127 281 { 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())); 129 290 } 130 291 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST) … … 140 301 } 141 302 else 142 dprintf(("VBoxGuestThread: DeviceIoControl failed with %d\n", GetLastError())); 143 303 dprintf(("VBoxGuestThread: DeviceIoControl (stat) failed with %d\n", GetLastError())); 144 304 } 145 305 } … … 155 315 } 156 316 } 317 /* Report statistics to the host */ 157 318 if ( gCtx.uStatInterval 158 319 && gCtx.pfnNtQuerySystemInformation) 159 320 { 160 SYSTEM_INFO systemInfo; 161 162 /* Query and report guest statistics */ 163 GetSystemInfo(&systemInfo); 164 165 //gCtx.pfnNtQuerySystemInformation( 321 VBoxGuestReportStatistics(pCtx); 166 322 } 167 323 }
Note:
See TracChangeset
for help on using the changeset viewer.