STDMETHODIMP Guest::InternalGetStatistics(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle, ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache, ULONG *aPageTotal, ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal) { CheckComArgOutPointerValid(aCpuUser); CheckComArgOutPointerValid(aCpuKernel); CheckComArgOutPointerValid(aCpuIdle); CheckComArgOutPointerValid(aMemTotal); CheckComArgOutPointerValid(aMemFree); CheckComArgOutPointerValid(aMemBalloon); CheckComArgOutPointerValid(aMemShared); CheckComArgOutPointerValid(aMemCache); CheckComArgOutPointerValid(aPageTotal); CheckComArgOutPointerValid(aMemAllocTotal); CheckComArgOutPointerValid(aMemFreeTotal); CheckComArgOutPointerValid(aMemBalloonTotal); CheckComArgOutPointerValid(aMemSharedTotal); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); *aCpuUser = mCurrentGuestStat[GUESTSTATTYPE_CPUUSER]; *aCpuKernel = mCurrentGuestStat[GUESTSTATTYPE_CPUKERNEL]; *aCpuIdle = mCurrentGuestStat[GUESTSTATTYPE_CPUIDLE]; *aMemTotal = mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemFree = mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemBalloon = mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemCache = mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K); /* page (4K) -> 1KB units */ *aPageTotal = mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */ /* MUST release all locks before calling any PGM statistics queries, * as they are executed by EMT and that might deadlock us by VMM device * activity which waits for the Guest object lock. */ alock.release(); Console::SafeVMPtr pVM (mParent); if (pVM.isOk()) { uint64_t uFreeTotal, uAllocTotal, uBalloonedTotal, uSharedTotal; *aMemFreeTotal = 0; int rc = PGMR3QueryGlobalMemoryStats(pVM.raw(), &uAllocTotal, &uFreeTotal, &uBalloonedTotal, &uSharedTotal); AssertRC(rc); if (rc == VINF_SUCCESS) { *aMemAllocTotal = (ULONG)(uAllocTotal / _1K); /* bytes -> KB */ *aMemFreeTotal = (ULONG)(uFreeTotal / _1K); *aMemBalloonTotal = (ULONG)(uBalloonedTotal / _1K); *aMemSharedTotal = (ULONG)(uSharedTotal / _1K); } else return E_FAIL; /* Query the missing per-VM memory statistics. */ *aMemShared = 0; uint64_t uTotalMem, uPrivateMem, uSharedMem, uZeroMem; rc = PGMR3QueryMemoryStats(pVM.raw(), &uTotalMem, &uPrivateMem, &uSharedMem, &uZeroMem); if (rc == VINF_SUCCESS) { *aMemShared = (ULONG)(uSharedMem / _1K); } else return E_FAIL; } else { *aMemAllocTotal = 0; *aMemFreeTotal = 0; *aMemBalloonTotal = 0; *aMemSharedTotal = 0; *aMemShared = 0; return E_FAIL; } return S_OK; }
void Guest::updateStats(uint64_t iTick) { uint64_t uFreeTotal, uAllocTotal, uBalloonedTotal, uSharedTotal; uint64_t uTotalMem, uPrivateMem, uSharedMem, uZeroMem; AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); ULONG aGuestStats[GUESTSTATTYPE_MAX]; RT_ZERO(aGuestStats); ULONG validStats = mGuestValidStats; /* Check if we have anything to report */ if (validStats) { mGuestValidStats = pm::GUESTSTATMASK_NONE; memcpy(aGuestStats, mCurrentGuestStat, sizeof(aGuestStats)); } alock.release(); /* * Calling SessionMachine may take time as the object resides in VBoxSVC * process. This is why we took a snapshot of currently collected stats * and released the lock. */ uFreeTotal = 0; uAllocTotal = 0; uBalloonedTotal = 0; uSharedTotal = 0; uTotalMem = 0; uPrivateMem = 0; uSharedMem = 0; uZeroMem = 0; Console::SafeVMPtr pVM (mParent); if (pVM.isOk()) { int rc; /* * There is no point in collecting VM shared memory if other memory * statistics are not available yet. Or is it? */ if (validStats) { /* Query the missing per-VM memory statistics. */ rc = PGMR3QueryMemoryStats(pVM.raw(), &uTotalMem, &uPrivateMem, &uSharedMem, &uZeroMem); if (rc == VINF_SUCCESS) { validStats |= pm::GUESTSTATMASK_MEMSHARED; } } if (mCollectVMMStats) { rc = PGMR3QueryGlobalMemoryStats(pVM.raw(), &uAllocTotal, &uFreeTotal, &uBalloonedTotal, &uSharedTotal); AssertRC(rc); if (rc == VINF_SUCCESS) { validStats |= pm::GUESTSTATMASK_ALLOCVMM|pm::GUESTSTATMASK_FREEVMM| pm::GUESTSTATMASK_BALOONVMM|pm::GUESTSTATMASK_SHAREDVMM; } } } mParent->reportGuestStatistics(validStats, aGuestStats[GUESTSTATTYPE_CPUUSER], aGuestStats[GUESTSTATTYPE_CPUKERNEL], aGuestStats[GUESTSTATTYPE_CPUIDLE], /* Convert the units for RAM usage stats: page (4K) -> 1KB units */ mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K), mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K), mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K), (ULONG)(uSharedMem / _1K), /* bytes -> KB */ mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K), mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K), (ULONG)(uAllocTotal / _1K), /* bytes -> KB */ (ULONG)(uFreeTotal / _1K), (ULONG)(uBalloonedTotal / _1K), (ULONG)(uSharedTotal / _1K)); }