Index: /trunk/src/VBox/VMM/VMMR3/PDMAsyncCompletionFile.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMAsyncCompletionFile.cpp	(revision 43622)
+++ /trunk/src/VBox/VMM/VMMR3/PDMAsyncCompletionFile.cpp	(revision 43623)
@@ -29,4 +29,5 @@
 #include <VBox/dbg.h>
 #include <VBox/vmm/uvm.h>
+#include <VBox/vmm/tm.h>
 
 #include <iprt/asm.h>
@@ -40,4 +41,5 @@
 #include <iprt/thread.h>
 #include <iprt/path.h>
+#include <iprt/rand.h>
 
 #include "PDMAsyncCompletionFileInternal.h"
@@ -72,5 +74,7 @@
     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "filename",     "Filename." },
     {  1,           1,          DBGCVAR_CAT_NUMBER,     0,                              "delay",        "Delay in milliseconds." },
-    {  1,           1,          DBGCVAR_CAT_NUMBER,     0,                              "reqs",         "Number of requests to delay." },
+    {  1,           1,          DBGCVAR_CAT_NUMBER,     0,                              "jitter",       "Jitter of the delay." },
+    {  1,           1,          DBGCVAR_CAT_NUMBER,     0,                              "reqs",         "Number of requests to delay." }
+
 };
 # endif
@@ -330,4 +334,5 @@
 #ifdef PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
             PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pTaskFile->Core.pEndpoint;
+            PPDMASYNCCOMPLETIONEPCLASSFILE  pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEpFile->Core.pEpClass;
 
             /* Check if we should delay completion of the request. */
@@ -335,8 +340,10 @@
                 && ASMAtomicReadU32(&pEpFile->cReqsDelay) > 0)
             {
+                uint64_t tsDelay = (RTRandU32() % 100) > 50 ? pEpFile->msDelay + (RTRandU32() % pEpFile->msJitter)
+                                                            : pEpFile->msDelay - (RTRandU32() % pEpFile->msJitter);
                 ASMAtomicDecU32(&pEpFile->cReqsDelay);
 
                 /* Arm the delay. */
-                pTaskFile->tsDelayEnd = RTTimeProgramMilliTS() + pEpFile->msDelay;
+                pTaskFile->tsDelayEnd = RTTimeProgramMilliTS() + tsDelay;
 
                 /* Append to the list. */
@@ -348,40 +355,15 @@
                 } while (!ASMAtomicCmpXchgPtr(&pEpFile->pDelayedHead, pTaskFile, pHead));
 
-                LogRel(("AIOMgr: Delaying request %#p for %u ms\n", pTaskFile, pEpFile->msDelay));
-                return;
+                if (tsDelay < pEpClassFile->cMilliesNext)
+                {
+                    ASMAtomicWriteU64(&pEpClassFile->cMilliesNext, tsDelay);
+                    TMTimerSetMillies(pEpClassFile->pTimer, tsDelay);
+                }
+
+                LogRel(("AIOMgr: Delaying request %#p for %u ms\n", pTaskFile, tsDelay));
             }
-#endif
-            pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core, pTaskFile->rc, true);
-
-#ifdef PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
-            /* Check for an expired delay. */
-            if (pEpFile->pDelayedHead != NULL)
-            {
-                uint64_t tsCur = RTTimeProgramMilliTS();
-                pTaskFile = ASMAtomicXchgPtrT(&pEpFile->pDelayedHead, NULL, PPDMASYNCCOMPLETIONTASKFILE);
-
-                while (pTaskFile)
-                {
-                    PPDMASYNCCOMPLETIONTASKFILE pTmp = pTaskFile;
-                    pTaskFile = pTaskFile->pDelayedNext;
-
-                    if (tsCur >= pTmp->tsDelayEnd)
-                    {
-                        LogRel(("AIOMgr: Delayed request %#p completed\n", pTmp));
-                        pdmR3AsyncCompletionCompleteTask(&pTmp->Core, pTmp->rc, true);
-                    }
-                    else
-                    {
-                        /* Prepend to the delayed list again. */
-                        PPDMASYNCCOMPLETIONTASKFILE pHead = NULL;
-                        do
-                        {
-                            pHead = ASMAtomicReadPtrT(&pEpFile->pDelayedHead, PPDMASYNCCOMPLETIONTASKFILE);
-                            pTmp->pDelayedNext = pHead;
-                        } while (!ASMAtomicCmpXchgPtr(&pEpFile->pDelayedHead, pTmp, pHead));
-                    }
-                }
-            }
-#endif
+            else
+#endif
+                pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core, pTaskFile->rc, true);
         }
     }
@@ -726,6 +708,9 @@
 
     uint32_t cReqsDelay = 1;
+    uint32_t msJitter = 0;
     if (cArgs == 4)
-        cReqsDelay = (uint32_t)pArgs[3].u.u64Number;
+        msJitter = (uint32_t)pArgs[3].u.u64Number;
+    if (cArgs == 5)
+        cReqsDelay = (uint32_t)pArgs[4].u.u64Number;
 
     /*
@@ -746,4 +731,5 @@
         ASMAtomicWriteSize(&pEpFile->enmTypeDelay, enmDelayType);
         ASMAtomicWriteU32(&pEpFile->msDelay, msDelay);
+        ASMAtomicWriteU32(&pEpFile->msJitter, msJitter);
         ASMAtomicWriteU32(&pEpFile->cReqsDelay, cReqsDelay);
 
@@ -758,4 +744,60 @@
     return VINF_SUCCESS;
 }
+
+static DECLCALLBACK(void) pdmacR3TimerCallback(PVM pVM, PTMTIMER pTimer, void *pvUser)
+{
+    uint64_t tsCur = RTTimeProgramMilliTS();
+    uint64_t cMilliesNext = UINT64_MAX;
+    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pvUser;
+
+    ASMAtomicWriteU64(&pEpClassFile->cMilliesNext, UINT64_MAX);
+
+    /* Go through all endpoints and check for expired requests. */
+    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEpClassFile->Core.pEndpointsHead;
+
+    while (pEpFile)
+    {
+        /* Check for an expired delay. */
+        if (pEpFile->pDelayedHead != NULL)
+        {
+            PPDMASYNCCOMPLETIONTASKFILE pTaskFile = ASMAtomicXchgPtrT(&pEpFile->pDelayedHead, NULL, PPDMASYNCCOMPLETIONTASKFILE);
+
+            while (pTaskFile)
+            {
+                PPDMASYNCCOMPLETIONTASKFILE pTmp = pTaskFile;
+                pTaskFile = pTaskFile->pDelayedNext;
+
+                if (tsCur >= pTmp->tsDelayEnd)
+                {
+                    LogRel(("AIOMgr: Delayed request %#p completed\n", pTmp));
+                    pdmR3AsyncCompletionCompleteTask(&pTmp->Core, pTmp->rc, true);
+                }
+                else
+                {
+                    /* Prepend to the delayed list again. */
+                    PPDMASYNCCOMPLETIONTASKFILE pHead = NULL;
+
+                    if (pTmp->tsDelayEnd - tsCur < cMilliesNext)
+                        cMilliesNext = pTmp->tsDelayEnd - tsCur;
+
+                    do
+                    {
+                        pHead = ASMAtomicReadPtrT(&pEpFile->pDelayedHead, PPDMASYNCCOMPLETIONTASKFILE);
+                        pTmp->pDelayedNext = pHead;
+                    } while (!ASMAtomicCmpXchgPtr(&pEpFile->pDelayedHead, pTmp, pHead));
+                }
+            }
+        }
+
+        pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEpFile->Core.pNext;
+    }
+
+    if (cMilliesNext < pEpClassFile->cMilliesNext)
+    {
+        ASMAtomicWriteU64(&pEpClassFile->cMilliesNext, cMilliesNext);
+        TMTimerSetMillies(pEpClassFile->pTimer, cMilliesNext);
+    }
+}
+
 # endif /* PDM_ASYNC_COMPLETION_FILE_WITH_DELAY */
 
@@ -836,4 +878,10 @@
         AssertRC(rc);
     }
+
+#ifdef PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
+    rc = TMR3TimerCreateInternal(pEpClassFile->Core.pVM, TMCLOCK_REAL, pdmacR3TimerCallback, pEpClassFile, "AC Delay", &pEpClassFile->pTimer);
+    AssertRC(rc);
+    pEpClassFile->cMilliesNext = UINT64_MAX;
+#endif
 #endif
 
Index: /trunk/src/VBox/VMM/include/PDMAsyncCompletionFileInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/PDMAsyncCompletionFileInternal.h	(revision 43622)
+++ /trunk/src/VBox/VMM/include/PDMAsyncCompletionFileInternal.h	(revision 43623)
@@ -45,5 +45,5 @@
 
 /** Enable for delay injection from the debugger. */
-#if 0
+#if 1
 # define PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
 #endif
@@ -272,4 +272,10 @@
     /** Flag whether the out of resources warning was printed already. */
     bool                                fOutOfResourcesWarningPrinted;
+#ifdef PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
+    /** Timer for delayed request completion. */
+    PTMTIMERR3                          pTimer;
+    /** Milliseconds until the next delay expires. */
+    volatile uint64_t                   cMilliesNext;
+#endif
 } PDMASYNCCOMPLETIONEPCLASSFILE;
 /** Pointer to the endpoint class data. */
@@ -380,4 +386,6 @@
     /** Request delay. */
     volatile uint32_t                      msDelay;
+    /** Request delay jitter. */
+    volatile uint32_t                      msJitter;
     /** Number of requests to delay. */
     volatile uint32_t                      cReqsDelay;
