VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp@ 27156

Last change on this file since 27156 was 27119, checked in by vboxsync, 15 years ago

comment

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.7 KB
Line 
1/* $Id: VBoxServiceBalloon.cpp 27119 2010-03-05 17:43:04Z vboxsync $ */
2/** @file
3 * VBoxService - Memory Ballooning.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <iprt/assert.h>
27#include <iprt/mem.h>
28#include <iprt/stream.h>
29#include <iprt/string.h>
30#include <iprt/semaphore.h>
31#include <iprt/system.h>
32#include <iprt/thread.h>
33#include <iprt/time.h>
34#include <VBox/VBoxGuestLib.h>
35#include "VBoxServiceInternal.h"
36#include "VBoxServiceUtils.h"
37
38
39
40/*******************************************************************************
41* Global Variables *
42*******************************************************************************/
43/** The balloon size. */
44static uint32_t g_cMemBalloonChunks = 0;
45
46/** The semaphore we're blocking on. */
47static RTSEMEVENTMULTI g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
48
49/** The array holding the R3 pointers of the balloon */
50static void **g_pavBalloon = NULL;
51
52
53/**
54 * Adapt the R0 memory balloon by granting/reclaiming 1MB chunks to/from R0.
55 *
56 * returns IPRT status code.
57 * @param cNewChunks The new number of 1MB chunks in the balloon.
58 */
59static int VBoxServiceBalloonSetUser(uint32_t cNewChunks)
60{
61 if (cNewChunks == g_cMemBalloonChunks)
62 return VINF_SUCCESS;
63
64 int rc = VINF_SUCCESS;
65 if (cNewChunks > g_cMemBalloonChunks)
66 {
67 /* inflate */
68 uint32_t i;
69 g_pavBalloon = (void**)RTMemRealloc(g_pavBalloon, cNewChunks * sizeof(void*));
70 for (i = g_cMemBalloonChunks; i < cNewChunks; i++)
71 {
72/** @todo r=bird: this isn't safe on linux. See suplibOsPageAlloc in
73 * SUPLib-linux.cpp. We should probably just fail outright here if
74 * linux, just in case...
75 * frank: To be more specific, the problem is fork(). */
76 void *pv = RTMemPageAlloc(VMMDEV_MEMORY_BALLOON_CHUNK_SIZE);
77 rc = VbglR3MemBalloonChange(pv, /* inflate=*/ true);
78 if (RT_SUCCESS(rc))
79 {
80 g_pavBalloon[i] = pv;
81 /* protect against access by dangling pointers (may fail) */
82 RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_NONE);
83 g_cMemBalloonChunks++;
84 }
85 else
86 {
87 RTMemPageFree(pv);
88 break;
89 }
90 }
91 }
92 else
93 {
94 /* deflate */
95 uint32_t i;
96 for (i = g_cMemBalloonChunks; i-- > cNewChunks;)
97 {
98 void *pv = g_pavBalloon[i];
99 rc = VbglR3MemBalloonChange(pv, /* inflate=*/ false);
100 if (RT_SUCCESS(rc))
101 {
102 /* unprotect */
103 RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
104 RTMemPageFree(g_pavBalloon[i]);
105 g_pavBalloon[i] = NULL;
106 g_cMemBalloonChunks--;
107 }
108 else
109 break;
110 }
111 }
112
113 return VINF_SUCCESS;
114}
115
116
117/** @copydoc VBOXSERVICE::pfnPreInit */
118static DECLCALLBACK(int) VBoxServiceBalloonPreInit(void)
119{
120 return VINF_SUCCESS;
121}
122
123
124/** @copydoc VBOXSERVICE::pfnOption */
125static DECLCALLBACK(int) VBoxServiceBalloonOption(const char **ppszShort, int argc, char **argv, int *pi)
126{
127 NOREF(ppszShort);
128 NOREF(argc);
129 NOREF(argv);
130 NOREF(pi);
131 return VINF_SUCCESS;
132}
133
134
135/** @copydoc VBOXSERVICE::pfnInit */
136static DECLCALLBACK(int) VBoxServiceBalloonInit(void)
137{
138 VBoxServiceVerbose(3, "VBoxServiceBalloonInit\n");
139
140 int rc = RTSemEventMultiCreate(&g_MemBalloonEvent);
141 AssertRCReturn(rc, rc);
142
143 g_cMemBalloonChunks = 0;
144 uint32_t cNewChunks = 0;
145 bool fHandleInR3;
146
147 /* Check balloon size */
148 rc = VbglR3MemBalloonRefresh(&cNewChunks, &fHandleInR3);
149 if (RT_SUCCESS(rc))
150 {
151 VBoxServiceVerbose(3, "VBoxMemBalloonInit: new balloon size %d MB (%s memory)\n",
152 cNewChunks, fHandleInR3 ? "R3" : "R0");
153 if (fHandleInR3)
154 rc = VBoxServiceBalloonSetUser(cNewChunks);
155 else
156 g_cMemBalloonChunks = cNewChunks;
157 }
158 else
159 VBoxServiceVerbose(3, "VBoxMemBalloonInit: VbglR3MemBalloonRefresh failed with %Rrc\n", rc);
160
161 /* We shouldn't fail here if ballooning isn't available. This can have several reasons,
162 * for instance, host too old (which is not that fatal). */
163 return VINF_SUCCESS;
164}
165
166
167/**
168 * Query the size of the memory balloon, given as a count of chunks.
169 *
170 * @returns The number of chunks (VMMDEV_MEMORY_BALLOON_CHUNK_SIZE).
171 */
172uint32_t VBoxServiceBalloonQueryChunks(void)
173{
174 return g_cMemBalloonChunks;
175}
176
177
178/** @copydoc VBOXSERVICE::pfnWorker */
179DECLCALLBACK(int) VBoxServiceBalloonWorker(bool volatile *pfShutdown)
180{
181 /* Start monitoring of the stat event change event. */
182 int rc = VbglR3CtlFilterMask(VMMDEV_EVENT_BALLOON_CHANGE_REQUEST, 0);
183 if (RT_FAILURE(rc))
184 {
185 VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3CtlFilterMask failed with %Rrc\n", rc);
186 return rc;
187 }
188
189 /*
190 * Tell the control thread that it can continue
191 * spawning services.
192 */
193 RTThreadUserSignal(RTThreadSelf());
194
195 /*
196 * Now enter the loop retrieving runtime data continuously.
197 */
198 for (;;)
199 {
200 uint32_t fEvents = 0;
201
202 /* Check if an update interval change is pending. */
203 rc = VbglR3WaitEvent(VMMDEV_EVENT_BALLOON_CHANGE_REQUEST, 0 /* no wait */, &fEvents);
204 if ( RT_SUCCESS(rc)
205 && (fEvents & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST))
206 {
207 uint32_t cNewChunks;
208 bool fHandleInR3;
209 rc = VbglR3MemBalloonRefresh(&cNewChunks, &fHandleInR3);
210 if (RT_SUCCESS(rc))
211 {
212 VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: new balloon size %d MB (%s memory)\n",
213 cNewChunks, fHandleInR3 ? "R3" : "R0");
214 if (fHandleInR3)
215 rc = VBoxServiceBalloonSetUser(cNewChunks);
216 else
217 g_cMemBalloonChunks = cNewChunks;
218 }
219 else
220 VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3MemBalloonRefresh failed with %Rrc\n", rc);
221 }
222
223 /*
224 * Block for a while.
225 *
226 * The event semaphore takes care of ignoring interruptions and it
227 * allows us to implement service wakeup later.
228 */
229 if (*pfShutdown)
230 break;
231 int rc2 = RTSemEventMultiWait(g_MemBalloonEvent, 5000);
232 if (*pfShutdown)
233 break;
234 if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
235 {
236 VBoxServiceError("RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
237 rc = rc2;
238 break;
239 }
240 }
241
242 /* Cancel monitoring of the memory balloon change event. */
243 rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_BALLOON_CHANGE_REQUEST);
244 if (RT_FAILURE(rc))
245 VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3CtlFilterMask failed with %Rrc\n", rc);
246
247 RTSemEventMultiDestroy(g_MemBalloonEvent);
248 g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
249
250 VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: finished mem balloon change request thread\n");
251 return 0;
252}
253
254/** @copydoc VBOXSERVICE::pfnTerm */
255static DECLCALLBACK(void) VBoxServiceBalloonTerm(void)
256{
257 VBoxServiceVerbose(3, "VBoxServiceBalloonTerm\n");
258 return;
259}
260
261
262/** @copydoc VBOXSERVICE::pfnStop */
263static DECLCALLBACK(void) VBoxServiceBalloonStop(void)
264{
265 RTSemEventMultiSignal(g_MemBalloonEvent);
266}
267
268
269/**
270 * The 'memballoon' service description.
271 */
272VBOXSERVICE g_MemBalloon =
273{
274 /* pszName. */
275 "memballoon",
276 /* pszDescription. */
277 "Memory Ballooning",
278 /* pszUsage. */
279 NULL,
280 /* pszOptions. */
281 NULL,
282 /* methods */
283 VBoxServiceBalloonPreInit,
284 VBoxServiceBalloonOption,
285 VBoxServiceBalloonInit,
286 VBoxServiceBalloonWorker,
287 VBoxServiceBalloonStop,
288 VBoxServiceBalloonTerm
289};
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette