Index: /trunk/src/VBox/VMM/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/VMM/testcase/Makefile.kmk	(revision 23671)
+++ /trunk/src/VBox/VMM/testcase/Makefile.kmk	(revision 23672)
@@ -49,4 +49,5 @@
 ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
  PROGRAMS  += tstPDMAsyncCompletion
+ PROGRAMS  += tstPDMAsyncCompletionStress
 endif
 
@@ -222,4 +223,8 @@
 tstPDMAsyncCompletion_SOURCES          = tstPDMAsyncCompletion.cpp
 tstPDMAsyncCompletion_LIBS             = $(LIB_VMM) $(LIB_REM) $(LIB_RUNTIME)
+
+tstPDMAsyncCompletionStress_TEMPLATE         = VBOXR3EXE
+tstPDMAsyncCompletionStress_SOURCES          = tstPDMAsyncCompletionStress.cpp
+tstPDMAsyncCompletionStress_LIBS             = $(LIB_VMM) $(LIB_REM) $(LIB_RUNTIME)
 endif
 
Index: /trunk/src/VBox/VMM/testcase/tstPDMAsyncCompletionStress.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstPDMAsyncCompletionStress.cpp	(revision 23672)
+++ /trunk/src/VBox/VMM/testcase/tstPDMAsyncCompletionStress.cpp	(revision 23672)
@@ -0,0 +1,576 @@
+/* $Id$ */
+/** @file
+ * PDM Asynchronous Completion Stresstest.
+ *
+ * This testcase is for stress testing the async completion interface.
+ */
+
+/*
+ * Copyright (C) 2008-2009 Sun Microsystems, Inc.
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
+
+#include "../VMInternal.h" /* UVM */
+#include <VBox/vm.h>
+#include <VBox/uvm.h>
+#include <VBox/pdmasynccompletion.h>
+#include <VBox/vmm.h>
+#include <VBox/cpum.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <VBox/pdmapi.h>
+#include <VBox/pdmthread.h>
+#include <iprt/alloc.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/file.h>
+#include <iprt/initterm.h>
+#include <iprt/semaphore.h>
+#include <iprt/rand.h>
+#include <iprt/string.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/thread.h>
+#include <iprt/param.h>
+
+#define TESTCASE "tstPDMAsyncCompletionStress"
+
+/** Number of simultaneous open endpoints for reading and writing. */
+#define NR_OPEN_ENDPOINTS 10
+/** Test pattern size. */
+#define TEST_PATTERN_SIZE (100*_1M)
+/** Minimum file size. */
+#define FILE_SIZE_MIN (100 * _1M)
+/** Maximum file size. */
+#define FILE_SIZE_MAX (10000UL * _1M)
+/** Minimum segment size. */
+#define SEGMENT_SIZE_MIN (512)
+/** Maximum segment size. */
+#define SEGMENT_SIZE_MAX (TEST_PATTERN_SIZE)
+/** Maximum number of active tasks. */
+#define TASK_ACTIVE_MAX (1024)
+/** Maximum size of a transfer. */
+#define TASK_TRANSFER_SIZE_MAX (10*_1M)
+
+/**
+ * Structure defining a file segment.
+ */
+typedef struct PDMACTESTFILESEG
+{
+    /** Start offset in the file. */
+    RTFOFF                     off;
+    /** Size of the segment. */
+    size_t                     cbSegment;
+    /** Pointer to the start of the data in the test pattern used for the segment. */
+    uint8_t                   *pbData;
+} PDMACTESTFILESEG, *PPDMACTESTFILESEG;
+
+/**
+ * Structure defining a I/O task.
+ */
+typedef struct PDMACTESTFILETASK
+{
+    /** Flag whether the task is currently active. */
+    bool                        fActive;
+    /** Flag whether this is a write. */
+    bool                        fWrite;
+    /** Start offset. */
+    RTFOFF                      off;
+    /** Data segment */
+    PDMDATASEG                  DataSeg;
+    /** Task handle. */
+    PPDMASYNCCOMPLETIONTASK     hTask;
+} PDMACTESTFILETASK, *PPDMACTESTFILETASK;
+
+/**
+ * Structure defining a test file.
+ */
+typedef struct PDMACTESTFILE
+{
+    /** The PDM async completion endpoint handle. */
+    PPDMASYNCCOMPLETIONENDPOINT hEndpoint;
+    /** Template used for this file. */
+    PPDMASYNCCOMPLETIONTEMPLATE pTemplate;
+    /** Maximum size of the file. */
+    uint64_t                   cbFileMax;
+    /** Current size of the file. */
+    uint64_t                   cbFileCurr;
+    /** Size of a file segment. */
+    size_t                     cbFileSegment;
+    /** Maximum number of segments. */
+    unsigned                   cSegments;
+    /** Pointer to the array describing how the file is assembled
+     * of the test pattern. Used for comparing read data to ensure
+     * that no corruption occured.
+     */
+    PPDMACTESTFILESEG          paSegs;
+    /** Maximum number of active tasks for this endpoint. */
+    uint32_t                   cTasksActiveMax;
+    /** Number of current active tasks. */
+    volatile uint32_t          cTasksActiveCurr;
+    /** Pointer to the array of task. */
+    PPDMACTESTFILETASK         paTasks; 
+    /** I/O thread handle. */
+    PPDMTHREAD                 hThread;
+    /** Flag whether the thread should terminate. */
+    bool                       fRunning;
+} PDMACTESTFILE, *PPDMACTESTFILE;
+
+/** Buffer storing the random test pattern. */
+uint8_t *g_pbTestPattern = NULL;
+/** Size of the test pattern. */
+size_t   g_cbTestPattern;
+/** Array holding test files. */
+PDMACTESTFILE g_aTestFiles[NR_OPEN_ENDPOINTS];
+
+static void tstPDMACStressTestFileVerify(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
+{
+    size_t   cbLeft = pTestTask->DataSeg.cbSeg;
+    RTFOFF   off    = pTestTask->off;
+    uint8_t *pbBuf  = (uint8_t *)pTestTask->DataSeg.pvSeg;
+
+    while (cbLeft)
+    {
+        size_t cbCompare; 
+        unsigned iSeg = off / pTestFile->cbFileSegment;;
+        PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[iSeg];
+        uint8_t *pbTestPattern;
+        unsigned offSeg = off - pSeg->off;
+
+        cbCompare = RT_MIN(cbLeft, pSeg->cbSegment - offSeg);
+        pbTestPattern = pSeg->pbData + offSeg;
+
+        if (memcmp(pbBuf, pbTestPattern, cbCompare))
+            AssertMsgFailed(("Unexpected data for off=%RTfoff size=%u\n", pTestTask->off, pTestTask->DataSeg.cbSeg));
+
+        pbBuf  += cbCompare;
+        off    += cbCompare;
+        cbLeft -= cbCompare;
+    }
+}
+
+static void tstPDMACStressTestFileFillBuffer(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
+{
+    uint8_t *pbBuf = (uint8_t *)pTestTask->DataSeg.pvSeg;
+    size_t  cbLeft = pTestTask->DataSeg.cbSeg;
+    RTFOFF  off    = pTestTask->off;
+
+    Assert(pTestTask->fWrite && pTestTask->fActive);
+
+    while (cbLeft)
+    {
+        size_t cbFill; 
+        unsigned iSeg = off / pTestFile->cbFileSegment;;
+        PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[iSeg];
+        uint8_t *pbTestPattern;
+        unsigned offSeg = off - pSeg->off;
+
+        cbFill = RT_MIN(cbLeft, pSeg->cbSegment - offSeg);
+        pbTestPattern = pSeg->pbData + offSeg;
+
+        memcpy(pbBuf, pbTestPattern, cbFill);
+
+        pbBuf  += cbFill;
+        off    += cbFill;
+        cbLeft -= cbFill;
+    }
+}
+
+static int tstPDMACStressTestFileWrite(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
+{
+    int rc = VINF_SUCCESS;
+
+    Assert(!pTestTask->fActive);
+
+    pTestTask->fActive       = true;
+    pTestTask->fWrite        = true;
+    pTestTask->DataSeg.cbSeg = RTRandU32Ex(512, TASK_TRANSFER_SIZE_MAX) & ~511;
+
+    RTFOFF offMax;
+
+    /* Did we reached the maximum file size */
+    if (pTestFile->cbFileCurr < pTestFile->cbFileMax)
+    {
+        offMax =   (pTestFile->cbFileMax - pTestFile->cbFileCurr) < pTestTask->DataSeg.cbSeg
+                 ? pTestFile->cbFileCurr + pTestTask->DataSeg.cbSeg
+                 : pTestFile->cbFileMax - pTestTask->DataSeg.cbSeg;
+    }
+    else
+        offMax = pTestFile->cbFileMax - pTestTask->DataSeg.cbSeg;
+
+    pTestTask->off = RTRandU64Ex(0, offMax) & ~511;
+
+    /* Set new file size of required */
+    if ((uint64_t)pTestTask->off + pTestTask->DataSeg.cbSeg > pTestFile->cbFileCurr)
+        pTestFile->cbFileCurr = pTestTask->off + pTestTask->DataSeg.cbSeg; 
+
+    /* Allocate data buffer. */
+    pTestTask->DataSeg.pvSeg = RTMemAlloc(pTestTask->DataSeg.cbSeg);
+    if (pTestTask->DataSeg.pvSeg)
+        return VERR_NO_MEMORY;
+
+    /* Fill data into buffer. */
+    tstPDMACStressTestFileFillBuffer(pTestFile, pTestTask);
+
+    /* Engage */
+    rc = PDMR3AsyncCompletionEpWrite(pTestFile->hEndpoint, pTestTask->off,
+                                     &pTestTask->DataSeg, 1,
+                                     pTestTask->DataSeg.cbSeg,
+                                     pTestTask,
+                                     &pTestTask->hTask);
+
+    return rc;
+}
+
+static int tstPDMACStressTestFileRead(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
+{
+    int rc = VINF_SUCCESS;
+
+    Assert(!pTestTask->fActive);
+
+    pTestTask->fActive       = true;
+    pTestTask->fWrite        = false;
+    pTestTask->DataSeg.cbSeg = RTRandU32Ex(1, RT_MIN(pTestFile->cbFileCurr, TASK_TRANSFER_SIZE_MAX));
+
+    AssertMsg(pTestFile->cbFileCurr >= pTestTask->DataSeg.cbSeg, ("Impossible\n"));
+    pTestTask->off = RTRandU64Ex(0, pTestFile->cbFileCurr - pTestTask->DataSeg.cbSeg); 
+
+    /* Allocate data buffer. */
+    pTestTask->DataSeg.pvSeg = RTMemAlloc(pTestTask->DataSeg.cbSeg);
+    if (pTestTask->DataSeg.pvSeg)
+        return VERR_NO_MEMORY;
+
+    /* Engage */
+    rc = PDMR3AsyncCompletionEpRead(pTestFile->hEndpoint, pTestTask->off,
+                                     &pTestTask->DataSeg, 1,
+                                     pTestTask->DataSeg.cbSeg,
+                                     pTestTask,
+                                     &pTestTask->hTask);
+
+    return rc;
+}
+
+/**
+ * Returns true with the given chance in percent.
+ *
+ * @returns true or false
+ * @param   iPercentage   The percentage of the chance to return true.
+ */
+static bool tstPDMACTestIsTrue(int iPercentage)
+{
+    int uRnd = RTRandU32Ex(0, 100);
+
+    return (uRnd < iPercentage); /* This should be enough for our purpose */
+}
+
+static int tstPDMACTestFileThread(PVM pVM, PPDMTHREAD pThread)
+{
+    PPDMACTESTFILE pTestFile = (PPDMACTESTFILE)pThread->pvUser;
+    int iWriteChance = 100; /* Chance to get a write task in percent. */
+    uint32_t cTasksStarted = 0;
+    int rc = VINF_SUCCESS;
+
+    while (pTestFile->fRunning)
+    {
+        unsigned iTaskCurr = 0;
+        
+
+        /* Fill all tasks */
+        while (   (pTestFile->cTasksActiveCurr < pTestFile->cTasksActiveMax)
+               && (iTaskCurr < pTestFile->cTasksActiveMax))
+        {
+            PPDMACTESTFILETASK pTask = &pTestFile->paTasks[iTaskCurr];
+
+            if (!pTask->fActive)
+            {
+                /* Read or write task? */
+                bool fWrite = tstPDMACTestIsTrue(iWriteChance);
+
+                ASMAtomicIncU32(&pTestFile->cTasksActiveCurr);
+
+                if (fWrite)
+                    rc = tstPDMACStressTestFileWrite(pTestFile, pTask);
+                else
+                    rc = tstPDMACStressTestFileRead(pTestFile, pTask);
+
+                AssertRC(rc);
+
+                cTasksStarted++;
+            }
+
+            iTaskCurr++;
+        }
+
+        /*
+         * Recalc write chance. The bigger the file the lower the chance to have a write.
+         * The minimum chance is 33 percent.
+         */
+        iWriteChance = (int)(((float)100.0 / pTestFile->cbFileMax) * (float)pTestFile->cbFileCurr);
+        iWriteChance = RT_MAX(33, iWriteChance);
+
+        /* Wait a random amount of time. (1ms - 10s) */
+        RTThreadSleep(RTRandU32Ex(1, 10000));
+    }
+
+    /* Wait for the rest to complete. */
+    while (pTestFile->cTasksActiveCurr)
+        RTThreadSleep(250);
+
+    RTPrintf("Thread exiting: processed %u tasks\n", cTasksStarted);
+    return rc;
+}
+
+static void tstPDMACStressTestFileTaskCompleted(PVM pVM, void *pvUser, void *pvUser2)
+{
+    PPDMACTESTFILE pTestFile = (PPDMACTESTFILE)pvUser2;
+    PPDMACTESTFILETASK pTestTask = (PPDMACTESTFILETASK)pvUser;
+
+    if (pTestTask->fWrite)
+    {
+        /* @todo Do something sensible here. */
+    }
+    else
+    {
+        tstPDMACStressTestFileVerify(pTestFile, pTestTask); /* Will assert if it fails */
+    }
+
+    RTMemFree(pTestTask->DataSeg.pvSeg);
+    pTestTask->fActive = false;
+    AssertMsg(pTestFile->cTasksActiveCurr > 0, ("Trying to complete a non active task\n"));
+    ASMAtomicDecU32(&pTestFile->cTasksActiveCurr);
+}
+
+/**
+ * Sets up a test file creating the I/O thread.
+ *
+ * @returns VBox status code.
+ * @param   pVM          Pointer to the shared VM instance structure.
+ * @param   pTestFile    Pointer to the uninitialized test file structure.
+ * @param   iTestId      Unique test id.
+ */
+static int tstPDMACStressTestFileOpen(PVM pVM, PPDMACTESTFILE pTestFile, unsigned iTestId)
+{
+    int rc = VERR_NO_MEMORY;
+
+    /* Size is a multiple of 512 */
+    pTestFile->cbFileMax     = RTRandU64Ex(FILE_SIZE_MIN, FILE_SIZE_MAX) & ~(511UL);
+    pTestFile->cbFileCurr    = 0;
+    pTestFile->cbFileSegment = RTRandU32Ex(SEGMENT_SIZE_MIN, RT_MIN(pTestFile->cbFileMax, SEGMENT_SIZE_MAX)) & ~((size_t)511); 
+
+    Assert(pTestFile->cbFileMax >= pTestFile->cbFileSegment);
+
+    /* Set up the segments array. */
+    pTestFile->cSegments  = pTestFile->cbFileMax / pTestFile->cbFileSegment;
+    pTestFile->cSegments += ((pTestFile->cbFileMax % pTestFile->cbFileSegment) > 0) ? 1 : 0;
+
+    pTestFile->paSegs = (PPDMACTESTFILESEG)RTMemAllocZ(pTestFile->cSegments * sizeof(PDMACTESTFILESEG));
+    if (pTestFile->paSegs)
+    {
+        /* Init the segments */
+        for (unsigned i = 0; i < pTestFile->cSegments; i++)
+        {
+            PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[i];
+
+            pSeg->off       = (RTFOFF)i * pTestFile->cbFileSegment;
+            pSeg->cbSegment = pTestFile->cbFileSegment;
+
+            /* Let the buffer point to a random position in the test pattern. */
+            uint32_t offTestPattern = RTRandU64Ex(0, g_cbTestPattern - pSeg->cbSegment);
+
+            pSeg->pbData = g_pbTestPattern + offTestPattern;
+        }
+
+        /* Init task array. */
+        pTestFile->cTasksActiveMax = RTRandU32Ex(1, TASK_ACTIVE_MAX);
+        pTestFile->paTasks         = (PPDMACTESTFILETASK)RTMemAllocZ(pTestFile->cTasksActiveMax * sizeof(PDMACTESTFILETASK));
+        if (pTestFile->paTasks)
+        {
+            /* Create the template */
+            char szDesc[256];
+
+            RTStrPrintf(szDesc, sizeof(szDesc), "Template-%d", iTestId);
+            rc = PDMR3AsyncCompletionTemplateCreateInternal(pVM, &pTestFile->pTemplate, tstPDMACStressTestFileTaskCompleted, pTestFile, szDesc);
+            if (RT_SUCCESS(rc))
+            {
+                /* Open the endpoint now. Because async completion endpoints cannot create files we have to do it before. */
+                char szFile[RTPATH_MAX];
+
+                RTStrPrintf(szFile, sizeof(szFile), "tstPDMAsyncCompletionStress-%d.tmp", iTestId);
+
+                RTFILE FileTmp;
+                rc = RTFileOpen(&FileTmp, szFile, RTFILE_O_CREATE | RTFILE_O_READWRITE);
+                if (RT_SUCCESS(rc))
+                {
+                    RTFileClose(FileTmp);
+
+                    rc = PDMR3AsyncCompletionEpCreateForFile(&pTestFile->hEndpoint, szFile, PDMACEP_FILE_FLAGS_CACHING, pTestFile->pTemplate);
+                    if (RT_SUCCESS(rc))
+                    {
+                        char szThreadDesc[256];
+
+                        pTestFile->fRunning = true;
+
+                        /* Create the thread creating the I/O for the given file. */
+                        RTStrPrintf(szThreadDesc, sizeof(szThreadDesc), "PDMACThread-%d", iTestId);
+                        rc = PDMR3ThreadCreate(pVM, &pTestFile->hThread, pTestFile, tstPDMACTestFileThread,
+                                               NULL, 0, RTTHREADTYPE_IO, szThreadDesc);
+                        if (RT_SUCCESS(rc))
+                        {
+                            RTPrintf(TESTCASE ": Created test file %s cbFileMax=%llu cbFileSegment=%u cSegments=%u cTasksActiveMax=%u\n",
+                                     szFile, pTestFile->cbFileMax, pTestFile->cbFileSegment, pTestFile->cSegments, pTestFile->cTasksActiveMax);
+                            return VINF_SUCCESS;
+                        }
+
+                        PDMR3AsyncCompletionEpClose(pTestFile->hEndpoint);
+                    }
+
+                    RTFileDelete(szFile);
+                }
+
+                PDMR3AsyncCompletionTemplateDestroy(pTestFile->pTemplate);
+            }
+
+            RTMemFree(pTestFile->paTasks);
+        }
+        else
+            rc = VERR_NO_MEMORY;
+
+        RTMemFree(pTestFile->paSegs);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    RTPrintf(TESTCASE ": Opening test file with id %d failed rc=%Rrc\n", iTestId, rc);
+
+    return rc;
+}
+
+/** 
+ * Closes a test file.
+ *
+ * @returns nothing.
+ * @param pTestFile    Pointer to the test file.
+ */
+static void tstPDMACStressTestFileClose(PPDMACTESTFILE pTestFile)
+{
+    int rcThread;
+    int rc;
+
+    RTPrintf("Terminating I/O thread, please wait...\n");
+
+    /* Let the thread know that it should terminate. */
+    pTestFile->fRunning = false;
+
+    /* Wait for the thread to terminate. */
+    rc = PDMR3ThreadDestroy(pTestFile->hThread, &rcThread);
+
+    RTPrintf("Thread terminated with status code rc=%Rrc\n", rcThread);
+
+    /* Free resources */
+    RTMemFree(pTestFile->paTasks);
+    RTMemFree(pTestFile->paSegs);
+    PDMR3AsyncCompletionEpClose(pTestFile->hEndpoint);
+    PDMR3AsyncCompletionTemplateDestroy(pTestFile->pTemplate);
+}
+
+/**
+ * Inits the test pattern.
+ *
+ * @returns VBox status code.
+ */
+static int tstPDMACStressTestPatternInit(void)
+{
+    RTPrintf(TESTCASE ": Creating test pattern. Please wait...\n");
+    g_cbTestPattern = TEST_PATTERN_SIZE;
+    g_pbTestPattern = (uint8_t *)RTMemAlloc(g_cbTestPattern);
+    if (!g_pbTestPattern)
+        return VERR_NO_MEMORY;
+
+    RTRandBytes(g_pbTestPattern, g_cbTestPattern);
+    return VINF_SUCCESS;
+}
+
+static void tstPDMACStressTestPatternDestroy(void)
+{
+    RTPrintf(TESTCASE ": Destroying test pattern\n");
+    RTMemFree(g_pbTestPattern);
+}
+
+int main(int argc, char *argv[])
+{
+    int rcRet = 0; /* error count */
+    int rc = VINF_SUCCESS;
+
+    RTR3InitAndSUPLib();
+
+    PVM pVM;
+    rc = VMR3Create(1, NULL, NULL, NULL, NULL, &pVM);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Little hack to avoid the VM_ASSERT_EMT assertion.
+         */
+        RTTlsSet(pVM->pUVM->vm.s.idxTLS, &pVM->pUVM->aCpus[0]);
+        pVM->pUVM->aCpus[0].pUVM = pVM->pUVM;
+        pVM->pUVM->aCpus[0].vm.s.NativeThreadEMT = RTThreadNativeSelf();
+
+        rc = tstPDMACStressTestPatternInit();
+        if (RT_SUCCESS(rc))
+        {
+            unsigned cFilesOpened = 0;
+
+            /* Open the endpoints. */
+            for (cFilesOpened = 0; cFilesOpened < NR_OPEN_ENDPOINTS; cFilesOpened++)
+            {
+                rc = tstPDMACStressTestFileOpen(pVM, &g_aTestFiles[cFilesOpened], cFilesOpened);
+                if (RT_FAILURE(rc))
+                    break;
+            }
+
+            if (RT_SUCCESS(rc))
+            {
+                /* Tests are running now. */
+                RTPrintf(TESTCASE ": Successfully opened all files. Running tests forever now or until an error is hit :)\n");
+                RTThreadSleep(RT_INDEFINITE_WAIT);
+            }
+
+            /* Close opened endpoints. */
+            for (unsigned i = 0; i < cFilesOpened; i++)
+                tstPDMACStressTestFileClose(&g_aTestFiles[i]);
+
+            tstPDMACStressTestPatternDestroy();
+        }
+        else
+        {
+            RTPrintf(TESTCASE ": failed to init test pattern!! rc=%Rrc\n", rc);
+            rcRet++;
+        }
+
+        rc = VMR3Destroy(pVM);
+        AssertMsg(rc == VINF_SUCCESS, ("%s: Destroying VM failed rc=%Rrc!!\n", __FUNCTION__, rc));
+    }
+    else
+    {
+        RTPrintf(TESTCASE ": failed to create VM!! rc=%Rrc\n", rc);
+        rcRet++;
+    }
+
+    return rcRet;
+}
+
