VBoxServiceBalloon.cpp revision 65d6ef67b3cf4d2f4c84af4d50439eb738d2ea31
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * VBoxService - Memory Ballooning.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * available from http://www.virtualbox.org. This file is free software;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * you can redistribute it and/or modify it under the terms of the GNU
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * General Public License (GPL) as published by the Free Software
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * additional information or have any questions.
2d97f8baccdd684bc0a8a15eb86bbe9ff2b85374vboxsync/*******************************************************************************
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync* Header Files *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync*******************************************************************************/
032703cba22135d6032705fc2d67dd1294a6491avboxsync/*******************************************************************************
032703cba22135d6032705fc2d67dd1294a6491avboxsync* Global Variables *
032703cba22135d6032705fc2d67dd1294a6491avboxsync*******************************************************************************/
032703cba22135d6032705fc2d67dd1294a6491avboxsync/** The balloon size. */
032703cba22135d6032705fc2d67dd1294a6491avboxsync/** The semaphore we're blocking on. */
032703cba22135d6032705fc2d67dd1294a6491avboxsyncstatic RTSEMEVENTMULTI g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
032703cba22135d6032705fc2d67dd1294a6491avboxsync/** The array holding the R3 pointers of the balloon */
315f68b04971772d94ba6c4408eaa19559a77cedvboxsync * Adapt the R0 memory balloon by granting/reclaiming 1MB chunks to/from R0.
032703cba22135d6032705fc2d67dd1294a6491avboxsync * returns IPRT status code.
315f68b04971772d94ba6c4408eaa19559a77cedvboxsync * @param cNewChunks The new number of 1MB chunks in the balloon.
032703cba22135d6032705fc2d67dd1294a6491avboxsyncstatic int VBoxServiceBalloonSetUser(uint32_t cNewChunks)
032703cba22135d6032705fc2d67dd1294a6491avboxsync /* inflate */
032703cba22135d6032705fc2d67dd1294a6491avboxsync g_pavBalloon = (void**)RTMemRealloc(g_pavBalloon, cNewChunks * sizeof(void*));
032703cba22135d6032705fc2d67dd1294a6491avboxsync/** @todo r=bird: this isn't safe on linux. See suplibOsPageAlloc in
032703cba22135d6032705fc2d67dd1294a6491avboxsync * SUPLib-linux.cpp. We should probably just fail outright here if
032703cba22135d6032705fc2d67dd1294a6491avboxsync * linux, just in case... */
032703cba22135d6032705fc2d67dd1294a6491avboxsync void *pv = RTMemPageAlloc(VMMDEV_MEMORY_BALLOON_CHUNK_SIZE);
032703cba22135d6032705fc2d67dd1294a6491avboxsync rc = VbglR3MemBalloonChange(pv, /* inflate=*/ true);
032703cba22135d6032705fc2d67dd1294a6491avboxsync /* protect against access by dangling pointers (may fail) */
032703cba22135d6032705fc2d67dd1294a6491avboxsync RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_NONE);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* deflate */
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync rc = VbglR3MemBalloonChange(pv, /* inflate=*/ false);
315f68b04971772d94ba6c4408eaa19559a77cedvboxsync /* unprotect */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync/** @copydoc VBOXSERVICE::pfnPreInit */
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsyncstatic DECLCALLBACK(int) VBoxServiceBalloonPreInit(void)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** @copydoc VBOXSERVICE::pfnOption */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic DECLCALLBACK(int) VBoxServiceBalloonOption(const char **ppszShort, int argc, char **argv, int *pi)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** @copydoc VBOXSERVICE::pfnInit */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic DECLCALLBACK(int) VBoxServiceBalloonInit(void)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync int rc = RTSemEventMultiCreate(&g_MemBalloonEvent);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* Check balloon size */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VbglR3MemBalloonRefresh(&cNewChunks, &fHandleInR3);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VBoxServiceVerbose(3, "VBoxMemBalloonInit: new balloon size %d MB (%s memory)\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VBoxServiceVerbose(3, "VBoxMemBalloonInit: VbglR3MemBalloonRefresh failed with %Rrc\n", rc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* We shouldn't fail here if ballooning isn't available. This can have several reasons,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * for instance, host too old (which is not that fatal). */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Query the size of the memory balloon, given as a count of chunks.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns The number of chunks (VMMDEV_MEMORY_BALLOON_CHUNK_SIZE).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** @copydoc VBOXSERVICE::pfnWorker */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncDECLCALLBACK(int) VBoxServiceBalloonWorker(bool volatile *pfShutdown)
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync /* Start monitoring of the stat event change event. */
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync int rc = VbglR3CtlFilterMask(VMMDEV_EVENT_BALLOON_CHANGE_REQUEST, 0);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3CtlFilterMask failed with %Rrc\n", rc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Tell the control thread that it can continue
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * spawning services.
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync * Now enter the loop retrieving runtime data continuously.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* Check if an update interval change is pending. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VbglR3WaitEvent(VMMDEV_EVENT_BALLOON_CHANGE_REQUEST, 0 /* no wait */, &fEvents);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync && (fEvents & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST))
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync rc = VbglR3MemBalloonRefresh(&cNewChunks, &fHandleInR3);
315f68b04971772d94ba6c4408eaa19559a77cedvboxsync VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: new balloon size %d MB (%s memory)\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3MemBalloonRefresh failed with %Rrc\n", rc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Block for a while.
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync * The event semaphore takes care of ignoring interruptions and it
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync * allows us to implement service wakeup later.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync int rc2 = RTSemEventMultiWait(g_MemBalloonEvent, 5000);
b6cedcca2caa8d1bb6310dfc0d51981c51b97014vboxsync VBoxServiceError("RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* Cancel monitoring of the memory balloon change event. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_BALLOON_CHANGE_REQUEST);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3CtlFilterMask failed with %Rrc\n", rc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: finished mem balloon change request thread\n");
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** @copydoc VBOXSERVICE::pfnTerm */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic DECLCALLBACK(void) VBoxServiceBalloonTerm(void)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** @copydoc VBOXSERVICE::pfnStop */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic DECLCALLBACK(void) VBoxServiceBalloonStop(void)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * The 'memballoon' service description.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* pszName. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync "memballoon",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* pszDescription. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync "Memory Ballooning",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* pszUsage. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* pszOptions. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* methods */