Index: /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxBalloonCtrl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxBalloonCtrl.cpp	(revision 36846)
+++ /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxBalloonCtrl.cpp	(revision 36847)
@@ -62,7 +62,4 @@
  * of a per-machine based one. */
 #define VBOX_BALLOONCTRL_GLOBAL_PERFCOL
-
-/** The semaphore we're blocking on. */
-static RTSEMEVENTMULTI g_BalloonControlEvent = NIL_RTSEMEVENTMULTI;
 
 /** The critical section for keep our stuff in sync. */
@@ -120,11 +117,11 @@
 };
 
-unsigned long g_ulTimeoutMS = 30 * 1000; /* Default is 30 seconds timeout. */
-unsigned long g_ulMemoryBalloonIncrementMB = 256;
-unsigned long g_ulMemoryBalloonDecrementMB = 128;
+static unsigned long g_ulTimeoutMS = 30 * 1000; /* Default is 30 seconds timeout. */
+static unsigned long g_ulMemoryBalloonIncrementMB = 256;
+static unsigned long g_ulMemoryBalloonDecrementMB = 128;
 /** Global balloon limit is 0, so disabled. Can be overridden by a per-VM
  *  "VBoxInternal/Guest/BalloonSizeMax" value. */
-unsigned long g_ulMemoryBalloonMaxMB = 0;
-unsigned long g_ulLowerMemoryLimitMB = 64;
+static unsigned long g_ulMemoryBalloonMaxMB = 0;
+static unsigned long g_ulLowerMemoryLimitMB = 64;
 
 /** Global objects. */
@@ -152,26 +149,26 @@
 typedef std::map<Bstr, VBOXBALLOONCTRL_MACHINE>::iterator mapVMIter;
 typedef std::map<Bstr, VBOXBALLOONCTRL_MACHINE>::const_iterator mapVMIterConst;
-mapVM g_mapVM;
+static mapVM g_mapVM;
 
 /* Prototypes. */
 #define serviceLogVerbose(a) if (g_fVerbose) { serviceLog a; }
-void serviceLog(const char *pszFormat, ...);
-
-bool machineIsRunning(MachineState_T enmState);
-mapVMIter machineGetByUUID(const Bstr &strUUID);
-int machineAdd(const ComPtr<IMachine> &rptrMachine);
-int machineUpdate(const ComPtr<IMachine> &rptrMachine, MachineState_T enmState);
-int machineUpdate(mapVMIter it, MachineState_T enmState);
-void machineRemove(mapVMIter it);
-
-unsigned long balloonGetMaxSize(const ComPtr<IMachine> &rptrMachine);
-bool balloonIsRequired(mapVMIter it);
-int balloonUpdate(mapVMIterConst it);
-
-HRESULT balloonCtrlSetup();
-void balloonCtrlShutdown();
-
-HRESULT createGlobalObjects();
-void deleteGlobalObjects();
+static void serviceLog(const char *pszFormat, ...);
+
+static bool machineIsRunning(MachineState_T enmState);
+static mapVMIter machineGetByUUID(const Bstr &strUUID);
+static int machineAdd(const ComPtr<IMachine> &rptrMachine);
+static int machineUpdate(const ComPtr<IMachine> &rptrMachine, MachineState_T enmState);
+static int machineUpdate(mapVMIter it, MachineState_T enmState);
+static void machineRemove(mapVMIter it);
+
+static unsigned long balloonGetMaxSize(const ComPtr<IMachine> &rptrMachine);
+static bool balloonIsRequired(mapVMIter it);
+static int balloonUpdate(mapVMIterConst it);
+
+static HRESULT balloonCtrlSetup();
+static void balloonCtrlShutdown();
+
+static HRESULT createGlobalObjects();
+static void deleteGlobalObjects();
 
 #ifdef RT_OS_WINDOWS
@@ -339,9 +336,9 @@
     ASMAtomicWriteBool(&g_fCanceled, true);
 
-    if (g_BalloonControlEvent != NIL_RTSEMEVENTMULTI)
-    {
-        int rc = RTSemEventMultiSignal(g_BalloonControlEvent);
+    if (!g_pEventQ)
+    {
+        int rc = g_pEventQ->interruptEventQueueProcessing();
         if (RT_FAILURE(rc))
-            serviceLog("Error: RTSemEventMultiSignal failed with rc=%Rrc\n");
+            serviceLog("Error: interruptEventQueueProcessing failed with rc=%Rrc\n", rc);
     }
 }
@@ -370,5 +367,5 @@
 }
 
-long getlBalloonDelta(unsigned long ulCurrentDesktopBalloonSize, unsigned long ulDesktopFreeMemory, unsigned long ulMaxBalloonSize)
+static long getlBalloonDelta(unsigned long ulCurrentDesktopBalloonSize, unsigned long ulDesktopFreeMemory, unsigned long ulMaxBalloonSize)
 {
     if (ulCurrentDesktopBalloonSize > ulMaxBalloonSize)
@@ -411,5 +408,5 @@
  * @param   enmState        The VM's machine state to judge whether it's running or not.
  */
-bool machineIsRunning(MachineState_T enmState)
+static bool machineIsRunning(MachineState_T enmState)
 {
     switch (enmState)
@@ -430,10 +427,10 @@
 }
 
-mapVMIter machineGetByUUID(const Bstr &strUUID)
+static mapVMIter machineGetByUUID(const Bstr &strUUID)
 {
     return g_mapVM.find(strUUID);
 }
 
-int machineAdd(const ComPtr<IMachine> &rptrMachine)
+static int machineAdd(const ComPtr<IMachine> &rptrMachine)
 {
     HRESULT rc;
@@ -451,5 +448,5 @@
         com::SafeIfaceArray<IPerformanceMetric> metricAffected;
 
-        Bstr strMetricNames(L"Guest/RAM*");
+        Bstr strMetricNames(L"Guest/RAM/Usage");
         strMetricNames.cloneTo(&metricNames[0]);
 
@@ -481,5 +478,5 @@
         g_mapVM.insert(std::make_pair(strUUID, m));
 
-        serviceLogVerbose(("Added machine \"%s\"\n", Utf8Str(strUUID).c_str()));
+        serviceLogVerbose(("Added machine \"%ls\"\n", strUUID.raw()));
 
     } while (0);
@@ -488,10 +485,10 @@
 }
 
-void machineRemove(mapVMIter it)
+static void machineRemove(mapVMIter it)
 {
     if (it != g_mapVM.end())
     {
         /* Must log before erasing the iterator because of the UUID ref! */
-        serviceLogVerbose(("Removing machine \"%s\"\n", Utf8Str(it->first).c_str()));
+        serviceLogVerbose(("Removing machine \"%ls\"\n", it->first.raw()));
 
         /*
@@ -502,5 +499,5 @@
 }
 
-int machineUpdate(const ComPtr<IMachine> &rptrMachine, MachineState_T enmState)
+static int machineUpdate(const ComPtr<IMachine> &rptrMachine, MachineState_T enmState)
 {
     if (   !balloonGetMaxSize(rptrMachine)
@@ -512,5 +509,5 @@
 }
 
-int machineUpdate(mapVMIter it, MachineState_T enmState)
+static int machineUpdate(mapVMIter it, MachineState_T enmState)
 {
     Assert(it != g_mapVM.end());
@@ -526,5 +523,5 @@
 }
 
-int getMetric(mapVMIterConst it, const Bstr& strName, LONG *pulData)
+static int getMetric(mapVMIterConst it, const Bstr& strName, LONG *pulData)
 {
     AssertPtrReturn(pulData, VERR_INVALID_PARAMETER);
@@ -595,5 +592,5 @@
  * @param   rptrMachine             Pointer to specified machine.
  */
-unsigned long balloonGetMaxSize(const ComPtr<IMachine> &rptrMachine)
+static unsigned long balloonGetMaxSize(const ComPtr<IMachine> &rptrMachine)
 {
     /*
@@ -637,5 +634,5 @@
  * @param   it          Iterator pointing to the VM to be processed.
  */
-bool balloonIsRequired(mapVMIter it)
+static bool balloonIsRequired(mapVMIter it)
 {
     /* Only do ballooning if we have a maximum balloon size set. */
@@ -652,5 +649,5 @@
  * @param   it          Iterator pointing to the VM to be processed.
  */
-int balloonUpdate(mapVMIterConst it)
+static int balloonUpdate(mapVMIterConst it)
 {
     /*
@@ -669,5 +666,5 @@
         {
 #ifdef DEBUG
-            serviceLogVerbose(("%s: No metrics available yet!\n", Utf8Str(it->first).c_str()));
+            serviceLogVerbose(("%ls: No metrics available yet!\n", it->first.raw()));
 #endif
             return VINF_SUCCESS;
@@ -677,6 +674,6 @@
         lBalloonCur /= 1024;
 
-        serviceLogVerbose(("%s: Balloon: %ld, Free mem: %ld, Max ballon: %ld\n",
-                           Utf8Str(it->first).c_str(),
+        serviceLogVerbose(("%ls: Balloon: %ld, Free mem: %ld, Max ballon: %ld\n",
+                           it->first.raw(),
                            lBalloonCur, lMemFree, it->second.ulBalloonSizeMax));
 
@@ -688,6 +685,6 @@
             Assert(lBalloonCur > 0);
 
-            serviceLog("%s: %s balloon by %ld to %ld ...\n",
-                       Utf8Str(it->first).c_str(),
+            serviceLog("%ls: %s balloon by %ld to %ld ...\n",
+                       it->first.raw(),
                        lDelta > 0 ? "Inflating" : "Deflating", lDelta, lBalloonCur);
 
@@ -708,6 +705,6 @@
                     CHECK_ERROR_BREAK(guest, COMSETTER(MemoryBalloonSize)(lBalloonCur));
                 else
-                    serviceLog("Error: Unable to set new balloon size %ld for machine \"%s\", rc=%Rhrc",
-                               lBalloonCur, Utf8Str(it->first).c_str(), rc);
+                    serviceLog("Error: Unable to set new balloon size %ld for machine \"%ls\", rc=%Rhrc",
+                               lBalloonCur, it->first.raw(), rc);
             } while (0);
 
@@ -717,10 +714,10 @@
     }
     else
-        serviceLog("Error: Unable to retrieve metrics for machine \"%s\", rc=%Rrc",
-                   Utf8Str(it->first).c_str(), vrc);
+        serviceLog("Error: Unable to retrieve metrics for machine \"%ls\", rc=%Rrc",
+                   it->first.raw(), vrc);
     return vrc;
 }
 
-void vmListDestroy()
+static void vmListDestroy()
 {
     serviceLogVerbose(("Destroying VM list ...\n"));
@@ -746,5 +743,5 @@
 }
 
-int vmListBuild()
+static int vmListBuild()
 {
     serviceLogVerbose(("Building VM list ...\n"));
@@ -779,6 +776,6 @@
                     if (!fAccessible)
                     {
-                        serviceLogVerbose(("Machine \"%s\" is inaccessible, skipping\n",
-                                           Utf8Str(strUUID).c_str()));
+                        serviceLogVerbose(("Machine \"%ls\" is inaccessible, skipping\n",
+                                           strUUID.raw()));
                         continue;
                     }
@@ -788,6 +785,6 @@
 
                     if (g_fVerbose)
-                        serviceLogVerbose(("Processing machine \"%s\" (state: %ld)\n",
-                                           Utf8Str(strUUID).c_str(), machineState));
+                        serviceLogVerbose(("Processing machine \"%ls\" (state: %ld)\n",
+                                           strUUID.raw(), machineState));
 
                     if (machineIsRunning(machineState))
@@ -811,6 +808,12 @@
 }
 
-int balloonCtrlCheck()
-{
+static int balloonCtrlCheck()
+{
+    static uint64_t uLast = UINT64_MAX;
+    uint64_t uNow = RTTimeProgramMilliTS() / g_ulTimeoutMS;
+    if (uLast == uNow)
+        return VINF_SUCCESS;
+    uLast = uNow;
+
     int rc = RTCritSectEnter(&g_MapCritSect);
     if (RT_SUCCESS(rc))
@@ -838,5 +841,5 @@
 }
 
-HRESULT balloonCtrlSetup()
+static HRESULT balloonCtrlSetup()
 {
     HRESULT rc = S_OK;
@@ -868,5 +871,5 @@
 }
 
-void balloonCtrlShutdown()
+static void balloonCtrlShutdown()
 {
     serviceLog("Shutting down ballooning ...\n");
@@ -879,5 +882,5 @@
 }
 
-RTEXITCODE balloonCtrlMain(HandlerArg *a)
+static RTEXITCODE balloonCtrlMain(HandlerArg *a)
 {
     HRESULT rc = S_OK;
@@ -885,11 +888,10 @@
     do
     {
+        int vrc = VINF_SUCCESS;
+
         /* Initialize global weak references. */
         g_pEventQ = com::EventQueue::getMainEventQueue();
 
         RTCritSectInit(&g_MapCritSect);
-
-        int vrc = RTSemEventMultiCreate(&g_BalloonControlEvent);
-        AssertRCReturn(vrc, RTEXITCODE_FAILURE);
 
         /*
@@ -945,16 +947,9 @@
              * processes NULL events signalling event loop termination.
              */
-            g_pEventQ->processEventQueue(500);
+            g_pEventQ->processEventQueue(g_ulTimeoutMS / 10);
 
             if (g_fCanceled)
             {
                 serviceLog("Signal caught, exiting ...\n");
-                break;
-            }
-
-            vrc = RTSemEventMultiWait(g_BalloonControlEvent, g_ulTimeoutMS);
-            if (vrc != VERR_TIMEOUT && RT_FAILURE(vrc))
-            {
-                serviceLog("Error: RTSemEventMultiWait failed; rc=%Rrc\n", vrc);
                 break;
             }
@@ -980,6 +975,4 @@
 
         RTCritSectDelete(&g_MapCritSect);
-        RTSemEventMultiDestroy(g_BalloonControlEvent);
-        g_BalloonControlEvent = NIL_RTSEMEVENTMULTI;
 
         if (RT_FAILURE(vrc))
@@ -991,5 +984,5 @@
 }
 
-void serviceLog(const char *pszFormat, ...)
+static void serviceLog(const char *pszFormat, ...)
 {
     va_list args;
@@ -1004,5 +997,5 @@
 }
 
-void logHeaderFooter(PRTLOGGER pLoggerRelease, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
+static void logHeaderFooter(PRTLOGGER pLoggerRelease, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
 {
     /* Some introductory information. */
@@ -1072,5 +1065,5 @@
 }
 
-void displayHelp()
+static void displayHelp()
 {
     RTStrmPrintf(g_pStdErr, "\nUsage: VBoxBalloonCtrl [options]\n\nSupported options (default values in brackets):\n");
@@ -1148,5 +1141,5 @@
 }
 
-void deleteGlobalObjects()
+static void deleteGlobalObjects()
 {
     serviceLogVerbose(("Deleting local objects ...\n"));
@@ -1161,5 +1154,5 @@
  * @return  HRESULT
  */
-HRESULT createGlobalObjects()
+static HRESULT createGlobalObjects()
 {
     serviceLogVerbose(("Creating local objects ...\n"));
@@ -1213,4 +1206,6 @@
             case 'i': /* Interval. */
                 g_ulTimeoutMS = ValueUnion.u32;
+                if (g_ulTimeoutMS < 500)
+                    g_ulTimeoutMS = 500;
                 break;
 
