Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 59849)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 59850)
@@ -2364,4 +2364,5 @@
          * Insufficient, must wait for it to arrive.
          */
+/** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
         STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
         for (uint32_t i = 0;; i++)
@@ -2448,5 +2449,5 @@
 
     /*
-     * Signal the semaphore to make sure we don't wait for 250 after a
+     * Signal the semaphore to make sure we don't wait for 250ms after a
      * suspend & resume scenario (see vmsvgaFIFOGetCmdPayload).
      */
@@ -2460,5 +2461,23 @@
     AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
 
+    /*
+     * Polling/sleep interval config.
+     *
+     * We wait for an a short interval if the guest has recently given us work
+     * to do, but the interval increases the longer we're kept idle.  With the
+     * current parameters we'll be at a 64ms poll interval after 1 idle second,
+     * at 90ms after 2 seconds, and reach the max 250ms interval after about
+     * 16 seconds.
+     */
+    RTMSINTERVAL const  cMsMinSleep = 16;
+    RTMSINTERVAL const  cMsIncSleep = 2;
+    RTMSINTERVAL const  cMsMaxSleep = 250;
+    RTMSINTERVAL        cMsSleep    = cMsMaxSleep;
+
+    /*
+     * The FIFO loop.
+     */
     LogFlow(("vmsvgaFIFOLoop: started loop\n"));
+    bool fBadOrDisabledFifo = false;
     uint32_t volatile * const pFIFO = pThis->svga.pFIFOR3;
     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
@@ -2473,17 +2492,28 @@
 
         /*
-         * Wait for at most 50 ms to start polling.
+         * Unless there's already work pending, go to sleep for a short while.
+         * (See polling/sleep interval config above.)
          */
-        rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, 50);
-        AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
-        if (pThread->enmState != PDMTHREADSTATE_RUNNING)
-        {
-            LogFlow(("vmsvgaFIFOLoop: thread state %x\n", pThread->enmState));
-            break;
-        }
+        if (   fBadOrDisabledFifo
+            || pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
+        {
+            rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, cMsSleep);
+            AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
+            if (pThread->enmState != PDMTHREADSTATE_RUNNING)
+            {
+                LogFlow(("vmsvgaFIFOLoop: thread state %x\n", pThread->enmState));
+                break;
+            }
+        }
+        else
+            rc = VINF_SUCCESS;
+        fBadOrDisabledFifo = false;
         if (rc == VERR_TIMEOUT)
         {
             if (pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
+            {
+                cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
                 continue;
+            }
             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
 
@@ -2492,4 +2522,5 @@
         else if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
+        cMsSleep = cMsMinSleep;
 
         Log(("vmsvgaFIFOLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
@@ -2513,4 +2544,5 @@
         {
             vmsvgaFifoSetNotBusy(pThis, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
+            fBadOrDisabledFifo = true;
             continue;
         }
@@ -2536,4 +2568,5 @@
             LogRelMax(8, ("vmsvgaFIFOLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
             vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
+            fBadOrDisabledFifo = true;
             continue;
         }
