STAM.cpp revision ad55b2e987ca887b6c11ed9958d38827fbcc417c
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * STAM - The Statistics Manager.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Copyright (C) 2006-2013 Oracle Corporation
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * available from http://www.virtualbox.org. This file is free software;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * you can redistribute it and/or modify it under the terms of the GNU
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * General Public License (GPL) as published by the Free Software
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/** @page pg_stam STAM - The Statistics Manager
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * The purpose for the statistics manager is to present the rest of the system
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * with a somewhat uniform way of accessing VMM statistics. STAM sports a
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * couple of different APIs for accessing them: STAMR3EnumU, STAMR3SnapshotU,
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * STAMR3DumpU, STAMR3DumpToReleaseLogU and the debugger. Main is exposing the
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * XML based one, STAMR3SnapshotU.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * The rest of the VMM together with the devices and drivers registers their
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * statistics with STAM giving them a name. The name is hierarchical, the
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * components separated by slashes ('/') and must start with a slash.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Each item registered with STAM - also, half incorrectly, called a sample -
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * has a type, unit, visibility, data pointer and description associated with it
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * in addition to the name (described above). The type tells STAM what kind of
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * structure the pointer is pointing to. The visibility allows unused
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * statistics from cluttering the output or showing up in the GUI. All the bits
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * together makes STAM able to present the items in a sensible way to the user.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Some types also allows STAM to reset the data, which is very convenient when
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * digging into specific operations and such.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * PS. The VirtualBox Debugger GUI has a viewer for inspecting the statistics
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync * STAM provides. You will also find statistics in the release and debug logs.
6ffe15b8a1730e56a0a818da51c4e7a115da5763vboxsync * And as mentioned in the introduction, the debugger console features a couple
6ffe15b8a1730e56a0a818da51c4e7a115da5763vboxsync * of command: .stats and .statsreset.
6ffe15b8a1730e56a0a818da51c4e7a115da5763vboxsync * @see grp_stam
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/*******************************************************************************
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync* Header Files *
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync*******************************************************************************/
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/*#define USE_PDMCRITSECTRW - testing, not for production. */
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync/*******************************************************************************
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync* Structures and Typedefs *
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync*******************************************************************************/
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync * Argument structure for stamR3PrintOne().
5c1381fc884d30a749517579368ff6cb4b43e809vboxsync DECLCALLBACKMEMBER(void, pfnPrintf)(struct STAMR3PRINTONEARGS *pvArg, const char *pszFormat, ...);
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync * Argument structure to stamR3EnumOne().
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync * The snapshot status structure.
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync * Argument package passed to stamR3SnapshotOne, stamR3SnapshotPrintf and stamR3SnapshotOutput.
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** Pointer to the buffer start. */
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** Pointer to the buffer end. */
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** Pointer to the current buffer position. */
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** Pointer to the VM. */
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** The number of bytes allocated. */
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** The status code. */
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync /** Whether to include the description strings. */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Init record for a ring-0 statistic sample.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsynctypedef struct STAMR0SAMPLE
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync /** The GVMMSTATS structure offset of the variable. */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync /** The type. */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync /** The unit. */
e0dec59adb362e8486c0622785420ad10e720972vboxsync /** The name. */
e0dec59adb362e8486c0622785420ad10e720972vboxsync const char *pszName;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync /** The description. */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync const char *pszDesc;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/*******************************************************************************
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync* Internal Functions *
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync*******************************************************************************/
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsyncstatic int stamR3ResetOne(PSTAMDESC pDesc, void *pvArg);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic DECLCALLBACK(void) stamR3EnumLogPrintf(PSTAMR3PRINTONEARGS pvArg, const char *pszFormat, ...);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic DECLCALLBACK(void) stamR3EnumRelLogPrintf(PSTAMR3PRINTONEARGS pvArg, const char *pszFormat, ...);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic DECLCALLBACK(void) stamR3EnumPrintf(PSTAMR3PRINTONEARGS pvArg, const char *pszFormat, ...);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic int stamR3SnapshotOne(PSTAMDESC pDesc, void *pvArg);
e0dec59adb362e8486c0622785420ad10e720972vboxsyncstatic int stamR3SnapshotPrintf(PSTAMR3SNAPSHOTONE pThis, const char *pszFormat, ...);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic int stamR3PrintOne(PSTAMDESC pDesc, void *pvArg);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic int stamR3EnumOne(PSTAMDESC pDesc, void *pvArg);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic bool stamR3MultiMatch(const char * const *papszExpressions, unsigned cExpressions, unsigned *piExpression, const char *pszName);
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsyncstatic char ** stamR3SplitPattern(const char *pszPat, unsigned *pcExpressions, char **ppszCopy);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic int stamR3EnumU(PUVM pUVM, const char *pszPat, bool fUpdateRing0, int (pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsyncstatic void stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat);
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsyncstatic void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions);
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsyncstatic DECLCALLBACK(void) stamR3EnumDbgfPrintf(PSTAMR3PRINTONEARGS pArgs, const char *pszFormat, ...);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/*******************************************************************************
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync* Global Variables *
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync*******************************************************************************/
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/** Pattern argument. */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "pattern", "Which samples the command shall be applied to. Use '*' as wildcard. Use ';' to separate expression." }
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/** Command descriptors. */
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync /* pszCmd, cArgsMin, cArgsMax, paArgDesc, cArgDescs, fFlags, pfnHandler pszSyntax, ....pszDescription */
e0dec59adb362e8486c0622785420ad10e720972vboxsync { "stats", 0, 1, &g_aArgPat[0], RT_ELEMENTS(g_aArgPat), 0, stamR3CmdStats, "[pattern]", "Display statistics." },
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync { "statsreset", 0, 1, &g_aArgPat[0], RT_ELEMENTS(g_aArgPat), 0, stamR3CmdStatsReset,"[pattern]", "Resets statistics." }
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * The GVMM mapping records - sans the host cpus.
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cHaltCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/HaltCalls", "The number of calls to GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cHaltBlocking), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/HaltBlocking", "The number of times we did go to sleep in GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cHaltTimeouts), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/HaltTimeouts", "The number of times we timed out in GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cHaltNotBlocking), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/HaltNotBlocking", "The number of times we didn't go to sleep in GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cHaltWakeUps), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/HaltWakeUps", "The number of wake ups done during GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cWakeUpCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/WakeUpCalls", "The number of calls to GVMMR0WakeUp." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cWakeUpNotHalted), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/WakeUpNotHalted", "The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp was called." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cWakeUpWakeUps), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/WakeUpWakeUps", "The number of wake ups done during GVMMR0WakeUp (not counting the explicit one)." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cPokeCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PokeCalls", "The number of calls to GVMMR0Poke." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cPokeNotBusy), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PokeNotBusy", "The number of times the EMT thread wasn't actually busy when GVMMR0Poke was called." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cPollCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PollCalls", "The number of calls to GVMMR0SchedPoll." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cPollHalts), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PollHalts", "The number of times the EMT has halted in a GVMMR0SchedPoll call." },
{ RT_UOFFSETOF(GVMMSTATS, SchedVM.cPollWakeUps), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PollWakeUps", "The number of wake ups done during GVMMR0SchedPoll." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cHaltCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/HaltCalls", "The number of calls to GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cHaltBlocking), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/HaltBlocking", "The number of times we did go to sleep in GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cHaltTimeouts), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/HaltTimeouts", "The number of times we timed out in GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cHaltNotBlocking), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/HaltNotBlocking", "The number of times we didn't go to sleep in GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cHaltWakeUps), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/HaltWakeUps", "The number of wake ups done during GVMMR0SchedHalt." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cWakeUpCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/WakeUpCalls", "The number of calls to GVMMR0WakeUp." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cWakeUpNotHalted), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/WakeUpNotHalted", "The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp was called." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cWakeUpWakeUps), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/WakeUpWakeUps", "The number of wake ups done during GVMMR0WakeUp (not counting the explicit one)." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cPokeCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PokeCalls", "The number of calls to GVMMR0Poke." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cPokeNotBusy), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PokeNotBusy", "The number of times the EMT thread wasn't actually busy when GVMMR0Poke was called." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cPollCalls), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PollCalls", "The number of calls to GVMMR0SchedPoll." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cPollHalts), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PollHalts", "The number of times the EMT has halted in a GVMMR0SchedPoll call." },
{ RT_UOFFSETOF(GVMMSTATS, SchedSum.cPollWakeUps), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PollWakeUps", "The number of wake ups done during GVMMR0SchedPoll." },
{ RT_UOFFSETOF(GVMMSTATS, cVMs), STAMTYPE_U32, STAMUNIT_CALLS, "/GVMM/VMs", "The number of VMs accessible to the caller." },
{ RT_UOFFSETOF(GVMMSTATS, cEMTs), STAMTYPE_U32, STAMUNIT_CALLS, "/GVMM/EMTs", "The number of emulation threads." },
{ RT_UOFFSETOF(GVMMSTATS, cHostCpus), STAMTYPE_U32, STAMUNIT_CALLS, "/GVMM/HostCPUs", "The number of host CPUs." },
{ RT_UOFFSETOF(GMMSTATS, cMaxPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cMaxPages", "The maximum number of pages GMM is allowed to allocate." },
{ RT_UOFFSETOF(GMMSTATS, cReservedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cReservedPages", "The number of pages that has been reserved." },
{ RT_UOFFSETOF(GMMSTATS, cOverCommittedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cOverCommittedPages", "The number of pages that we have over-committed in reservations." },
{ RT_UOFFSETOF(GMMSTATS, cAllocatedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cAllocatedPages", "The number of actually allocated (committed if you like) pages." },
{ RT_UOFFSETOF(GMMSTATS, cSharedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cSharedPages", "The number of pages that are shared. A subset of cAllocatedPages." },
{ RT_UOFFSETOF(GMMSTATS, cDuplicatePages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cDuplicatePages", "The number of pages that are actually shared between VMs." },
{ RT_UOFFSETOF(GMMSTATS, cLeftBehindSharedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cLeftBehindSharedPages", "The number of pages that are shared that has been left behind by VMs not doing proper cleanups." },
{ RT_UOFFSETOF(GMMSTATS, cBalloonedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/cBalloonedPages", "The number of current ballooned pages." },
{ RT_UOFFSETOF(GMMSTATS, cChunks), STAMTYPE_U32, STAMUNIT_COUNT, "/GMM/cChunks", "The number of allocation chunks." },
{ RT_UOFFSETOF(GMMSTATS, cFreedChunks), STAMTYPE_U32, STAMUNIT_COUNT, "/GMM/cFreedChunks", "The number of freed chunks ever." },
{ RT_UOFFSETOF(GMMSTATS, cShareableModules), STAMTYPE_U32, STAMUNIT_COUNT, "/GMM/cShareableModules", "The number of shareable modules." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.Reserved.cBasePages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/Reserved/cBasePages", "The amount of base memory (RAM, ROM, ++) reserved by the VM." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.Reserved.cShadowPages), STAMTYPE_U32, STAMUNIT_PAGES, "/GMM/VM/Reserved/cShadowPages", "The amount of memory reserved for shadow/nested page tables." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.Reserved.cFixedPages), STAMTYPE_U32, STAMUNIT_PAGES, "/GMM/VM/Reserved/cFixedPages", "The amount of memory reserved for fixed allocations like MMIO2 and the hyper heap." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.Allocated.cBasePages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/Allocated/cBasePages", "The amount of base memory (RAM, ROM, ++) allocated by the VM." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.Allocated.cShadowPages), STAMTYPE_U32, STAMUNIT_PAGES, "/GMM/VM/Allocated/cShadowPages", "The amount of memory allocated for shadow/nested page tables." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.Allocated.cFixedPages), STAMTYPE_U32, STAMUNIT_PAGES, "/GMM/VM/Allocated/cFixedPages", "The amount of memory allocated for fixed allocations like MMIO2 and the hyper heap." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cPrivatePages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cPrivatePages", "The current number of private pages." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cSharedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cSharedPages", "The current number of shared pages." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cBalloonedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cBalloonedPages", "The current number of ballooned pages." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cMaxBalloonedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cMaxBalloonedPages", "The max number of pages that can be ballooned." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cReqBalloonedPages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cReqBalloonedPages", "The number of pages we've currently requested the guest to give us." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cReqActuallyBalloonedPages),STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cReqActuallyBalloonedPages","The number of pages the guest has given us in response to the request." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cReqDeflatePages), STAMTYPE_U64, STAMUNIT_PAGES, "/GMM/VM/cReqDeflatePages", "The number of pages we've currently requested the guest to take back." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.cShareableModules), STAMTYPE_U32, STAMUNIT_COUNT, "/GMM/VM/cShareableModules", "The number of shareable modules traced by the VM." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.enmPolicy), STAMTYPE_U32, STAMUNIT_NONE, "/GMM/VM/enmPolicy", "The current over-commit policy." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.enmPriority), STAMTYPE_U32, STAMUNIT_NONE, "/GMM/VM/enmPriority", "The VM priority for arbitrating VMs in low and out of memory situation." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.fBallooningEnabled), STAMTYPE_BOOL, STAMUNIT_NONE, "/GMM/VM/fBallooningEnabled", "Whether ballooning is enabled or not." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.fBallooningEnabled), STAMTYPE_BOOL, STAMUNIT_NONE, "/GMM/VM/fSharedPagingEnabled", "Whether shared paging is enabled or not." },
{ RT_UOFFSETOF(GMMSTATS, VMStats.fBallooningEnabled), STAMTYPE_BOOL, STAMUNIT_NONE, "/GMM/VM/fMayAllocate", "Whether the VM is allowed to allocate memory or not." },
int rc;
#ifndef USE_PDMCRITSECTRW
#ifdef VBOX_WITH_DEBUGGER
static bool fRegisteredCmds = false;
if (!fRegisteredCmds)
fRegisteredCmds = true;
return VINF_SUCCESS;
while (pCur)
#ifndef USE_PDMCRITSECTRW
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
VMMR3DECL(int) STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
return stamR3RegisterU(pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
VMMR3DECL(int) STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
return stamR3RegisterU(pVM->pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
VMMR3DECL(int) STAMR3RegisterFU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
return rc;
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
VMMR3DECL(int) STAMR3RegisterF(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
int rc = STAMR3RegisterVU(pVM->pUVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
return rc;
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
VMMR3DECL(int) STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
char *pszFormattedName;
if (!pszFormattedName)
return VERR_NO_MEMORY;
int rc = STAMR3RegisterU(pUVM, pvSample, enmType, enmVisibility, pszFormattedName, enmUnit, pszDesc);
return rc;
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
VMMR3DECL(int) STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
return STAMR3RegisterVU(pVM->pUVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
* @param pfnReset Callback for resetting the sample. NULL should be used if the sample can't be reset.
* @remark There is currently no device or driver variant of this API. Add one if it should become necessary!
VMMR3DECL(int) STAMR3RegisterCallback(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
int rc = STAMR3RegisterCallbackV(pVM, pvSample, enmVisibility, enmUnit, pfnReset, pfnPrint, pszDesc, pszName, args);
return rc;
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
* @param pfnReset Callback for resetting the sample. NULL should be used if the sample can't be reset.
* @remark There is currently no device or driver variant of this API. Add one if it should become necessary!
VMMR3DECL(int) STAMR3RegisterCallbackV(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
char *pszFormattedName;
if (!pszFormattedName)
return VERR_NO_MEMORY;
int rc = stamR3RegisterU(pVM->pUVM, pvSample, pfnReset, pfnPrint, STAMTYPE_CALLBACK, enmVisibility, pszFormattedName, enmUnit, pszDesc);
return rc;
#ifdef VBOX_STRICT
* @param pfnReset Callback for resetting the sample. NULL should be used if the sample can't be reset.
* @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
* @remark There is currently no device or driver variant of this API. Add one if it should become necessary!
static int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
while (pCur)
if (iDiff > 0)
if (!iDiff)
return VERR_ALREADY_EXISTS;
if (pPrev)
if (pCur)
#ifdef VBOX_STRICT
switch (enmType)
case STAMTYPE_U64:
case STAMTYPE_U64_RESET:
case STAMTYPE_X64:
case STAMTYPE_X64_RESET:
case STAMTYPE_COUNTER:
case STAMTYPE_PROFILE:
case STAMTYPE_PROFILE_ADV:
case STAMTYPE_RATIO_U32:
case STAMTYPE_RATIO_U32_RESET:
case STAMTYPE_U32:
case STAMTYPE_U32_RESET:
case STAMTYPE_X32:
case STAMTYPE_X32_RESET:
case STAMTYPE_U16:
case STAMTYPE_U16_RESET:
case STAMTYPE_X16:
case STAMTYPE_X16_RESET:
case STAMTYPE_U8:
case STAMTYPE_U8_RESET:
case STAMTYPE_X8:
case STAMTYPE_X8_RESET:
case STAMTYPE_BOOL:
case STAMTYPE_BOOL_RESET:
case STAMTYPE_CALLBACK:
int rc;
if (pNew)
if (pszDesc)
if (pPrev)
return rc;
while (pCur)
if (pPrev)
return rc;
if (fGVMMMatched)
char *pszCopy;
unsigned cExpressions;
if (!papszExpressions)
return VERR_NO_MEMORY;
fGVMMMatched = true;
if (!fGVMMMatched)
fGMMMatched = true;
if (fGVMMMatched)
if (fGMMMatched)
return rc;
case STAMTYPE_COUNTER:
case STAMTYPE_PROFILE:
case STAMTYPE_PROFILE_ADV:
case STAMTYPE_RATIO_U32_RESET:
case STAMTYPE_CALLBACK:
case STAMTYPE_U8_RESET:
case STAMTYPE_X8_RESET:
case STAMTYPE_U16_RESET:
case STAMTYPE_X16_RESET:
case STAMTYPE_U32_RESET:
case STAMTYPE_X32_RESET:
case STAMTYPE_U64_RESET:
case STAMTYPE_X64_RESET:
case STAMTYPE_BOOL_RESET:
case STAMTYPE_U8:
case STAMTYPE_X8:
case STAMTYPE_U16:
case STAMTYPE_X16:
case STAMTYPE_U32:
case STAMTYPE_X32:
case STAMTYPE_U64:
case STAMTYPE_X64:
case STAMTYPE_RATIO_U32:
case STAMTYPE_BOOL:
return VINF_SUCCESS;
VMMR3DECL(int) STAMR3Snapshot(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc)
if (pcchSnapshot)
return rc;
case STAMTYPE_COUNTER:
return VINF_SUCCESS;
case STAMTYPE_PROFILE:
case STAMTYPE_PROFILE_ADV:
return VINF_SUCCESS;
stamR3SnapshotPrintf(pThis, "<Profile cPeriods=\"%lld\" cTicks=\"%lld\" cTicksMin=\"%lld\" cTicksMax=\"%lld\"",
case STAMTYPE_RATIO_U32:
case STAMTYPE_RATIO_U32_RESET:
if (pDesc->enmVisibility == STAMVISIBILITY_USED && !pDesc->u.pRatioU32->u32A && !pDesc->u.pRatioU32->u32B)
return VINF_SUCCESS;
case STAMTYPE_CALLBACK:
case STAMTYPE_U8:
case STAMTYPE_U8_RESET:
return VINF_SUCCESS;
case STAMTYPE_X8:
case STAMTYPE_X8_RESET:
return VINF_SUCCESS;
case STAMTYPE_U16:
case STAMTYPE_U16_RESET:
return VINF_SUCCESS;
case STAMTYPE_X16:
case STAMTYPE_X16_RESET:
return VINF_SUCCESS;
case STAMTYPE_U32:
case STAMTYPE_U32_RESET:
return VINF_SUCCESS;
case STAMTYPE_X32:
case STAMTYPE_X32_RESET:
return VINF_SUCCESS;
case STAMTYPE_U64:
case STAMTYPE_U64_RESET:
return VINF_SUCCESS;
case STAMTYPE_X64:
case STAMTYPE_X64_RESET:
return VINF_SUCCESS;
case STAMTYPE_BOOL:
case STAMTYPE_BOOL_RESET:
return VINF_SUCCESS;
case STAMVISIBILITY_ALWAYS:
case STAMVISIBILITY_USED:
case STAMVISIBILITY_NOT_GUI:
if (!pszBadChar)
switch (*pszBadChar)
} while (pszBadChar);
if (!pszNew)
return cch;
if (!pszSnapshot)
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(void) stamR3EnumLogPrintf(PSTAMR3PRINTONEARGS pArgs, const char *pszFormat, ...)
return VINF_SUCCESS;
static DECLCALLBACK(void) stamR3EnumRelLogPrintf(PSTAMR3PRINTONEARGS pArgs, const char *pszFormat, ...)
return VINF_SUCCESS;
case STAMTYPE_COUNTER:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8llu %s\n", pDesc->pszName, pDesc->u.pCounter->c, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_PROFILE:
case STAMTYPE_PROFILE_ADV:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8llu %s (%12llu ticks, %7llu times, max %9llu, min %7lld)\n", pDesc->pszName,
pDesc->u.pProfile->cTicks, pDesc->u.pProfile->cPeriods, pDesc->u.pProfile->cTicksMax, pDesc->u.pProfile->cTicksMin);
case STAMTYPE_RATIO_U32:
case STAMTYPE_RATIO_U32_RESET:
if (pDesc->enmVisibility == STAMVISIBILITY_USED && !pDesc->u.pRatioU32->u32A && !pDesc->u.pRatioU32->u32B)
return VINF_SUCCESS;
case STAMTYPE_CALLBACK:
case STAMTYPE_U8:
case STAMTYPE_U8_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8u %s\n", pDesc->pszName, *pDesc->u.pu8, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_X8:
case STAMTYPE_X8_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8x %s\n", pDesc->pszName, *pDesc->u.pu8, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_U16:
case STAMTYPE_U16_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8u %s\n", pDesc->pszName, *pDesc->u.pu16, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_X16:
case STAMTYPE_X16_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8x %s\n", pDesc->pszName, *pDesc->u.pu16, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_U32:
case STAMTYPE_U32_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8u %s\n", pDesc->pszName, *pDesc->u.pu32, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_X32:
case STAMTYPE_X32_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8x %s\n", pDesc->pszName, *pDesc->u.pu32, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_U64:
case STAMTYPE_U64_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8llu %s\n", pDesc->pszName, *pDesc->u.pu64, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_X64:
case STAMTYPE_X64_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %8llx %s\n", pDesc->pszName, *pDesc->u.pu64, STAMR3GetUnit(pDesc->enmUnit));
case STAMTYPE_BOOL:
case STAMTYPE_BOOL_RESET:
return VINF_SUCCESS;
pArgs->pfnPrintf(pArgs, "%-32s %s %s\n", pDesc->pszName, *pDesc->u.pf ? "true " : "false ", STAMR3GetUnit(pDesc->enmUnit));
return VINF_SUCCESS;
int rc;
return rc;
if (!pszCopy)
return NULL;
if (!papszExpressions)
return NULL;
if (++i >= cExpressions)
return papszExpressions;
if (fUpdateRing0)
while (pCur)
if (rc)
if (fUpdateRing0)
if (rc)
char *pszCopy;
unsigned cExpressions;
if (!papszExpressions)
return VERR_NO_MEMORY;
if (fUpdateRing0)
unsigned iExpression = 0;
if (rc)
return rc;
static void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions)
bool fUpdate = false;
fUpdate = true;
if (!fUpdate)
if (fUpdate)
fUpdate = false;
fUpdate = true;
if (fUpdate)
switch (enmUnit)
#ifdef VBOX_WITH_DEBUGGER
static DECLCALLBACK(int) stamR3CmdStats(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return stamR3EnumU(pUVM, cArgs ? paArgs[0].u.pszString : NULL, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
static DECLCALLBACK(void) stamR3EnumDbgfPrintf(PSTAMR3PRINTONEARGS pArgs, const char *pszFormat, ...)
static DECLCALLBACK(int) stamR3CmdStatsReset(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)