tstPDMAsyncCompletionStress.cpp revision 22ec733a5e041fcdfe02fce2eafc9faf8b0077dd
/* $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;
* 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 *
*******************************************************************************/
#include "../VMInternal.h" /* UVM */
#include <VBox/pdmasynccompletion.h>
#include <VBox/pdmthread.h>
#include <iprt/initterm.h>
#include <iprt/semaphore.h>
#define TESTCASE "tstPDMAsyncCompletionStress"
#if 0
/** Number of simultaneous open endpoints for reading and writing. */
#define NR_OPEN_ENDPOINTS 10
/** Test pattern size. */
/** Minimum file size. */
/** Maximum file size. */
/** 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. */
#else
/** Number of simultaneous open endpoints for reading and writing. */
#define NR_OPEN_ENDPOINTS 5
/** Test pattern size. */
/** Minimum file size. */
/** Maximum file size. */
/** 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 (1)
/** Maximum size of a transfer. */
#define TASK_TRANSFER_SIZE_MAX (_1M)
#endif
/**
* Structure defining a file segment.
*/
typedef struct PDMACTESTFILESEG
{
/** Start offset in the file. */
/** Size of the segment. */
/** Pointer to the start of the data in the test pattern used for the segment. */
/**
* 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. */
/** Data segment */
/** Task handle. */
/**
* Structure defining a test file.
*/
typedef struct PDMACTESTFILE
{
/** The PDM async completion endpoint handle. */
/** Template used for this file. */
/** Maximum size of the file. */
/** Current size of the file. */
/** Size of a file segment. */
/** 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.
*/
/** Maximum number of active tasks for this endpoint. */
/** Number of current active tasks. */
volatile uint32_t cTasksActiveCurr;
/** Pointer to the array of task. */
/** I/O thread handle. */
/** Flag whether the thread should terminate. */
bool fRunning;
/** Buffer storing the random test pattern. */
/** Size of the test pattern. */
/** Array holding test files. */
{
while (cbLeft)
{
{
unsigned idx = 0;
idx++;
RTMsgError("Unexpected data for off=%RTfoff size=%u\n"
"Expected %c got %c\n",
}
}
}
static void tstPDMACStressTestFileFillBuffer(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
{
while (cbLeft)
{
}
}
{
int rc = VINF_SUCCESS;
/* Did we reached the maximum file size */
{
: pTestFile->cbFileCurr;
}
else
/*
* If we reached the maximum file size write in the whole file
* otherwise we will enforce the range for random offsets to let it grow
* more quickly.
*/
offMin = 0;
else
/* Set new file size of required */
("Current file size (%llu) exceeds final size (%llu)\n",
/* Allocate data buffer. */
return VERR_NO_MEMORY;
/* Fill data into buffer. */
/* Engage */
return rc;
}
{
int rc = VINF_SUCCESS;
/* Allocate data buffer. */
return VERR_NO_MEMORY;
/* Engage */
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)
{
}
{
uint32_t cTasksStarted = 0;
int rc = VINF_SUCCESS;
return VINF_SUCCESS;
{
unsigned iTaskCurr = 0;
/* Fill all tasks */
{
{
/* Read or write task? */
if (fWrite)
else
if (rc != VINF_AIO_TASK_PENDING)
}
iTaskCurr++;
}
/*
* Recalc write chance. The bigger the file the lower the chance to have a write.
* The minimum chance is 33 percent.
*/
/* Wait a random amount of time. (1ms - 100ms) */
}
/* Wait for the rest to complete. */
while (pTestFile->cTasksActiveCurr)
RTThreadSleep(250);
return rc;
}
{
{
/* @todo Do something sensible here. */
}
else
{
}
}
/**
* 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.
*/
{
int rc = VERR_NO_MEMORY;
/* Size is a multiple of 512 */
pTestFile->cbFileCurr = 0;
pTestFile->cbFileSegment = RTRandU32Ex(SEGMENT_SIZE_MIN, RT_MIN(pTestFile->cbFileMax, SEGMENT_SIZE_MAX)) & ~((size_t)511);
/* Set up the segments array. */
pTestFile->paSegs = (PPDMACTESTFILESEG)RTMemAllocZ(pTestFile->cSegments * sizeof(PDMACTESTFILESEG));
{
/* Init the segments */
{
/* Let the buffer point to a random position in the test pattern. */
}
/* Init task array. */
pTestFile->paTasks = (PPDMACTESTFILETASK)RTMemAllocZ(pTestFile->cTasksActiveMax * sizeof(PDMACTESTFILETASK));
{
/* Create the template */
char szDesc[256];
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];
if (RT_SUCCESS(rc))
{
rc = PDMR3AsyncCompletionEpCreateForFile(&pTestFile->hEndpoint, szFile, PDMACEP_FILE_FLAGS_CACHING, pTestFile->pTemplate);
if (RT_SUCCESS(rc))
{
char szThreadDesc[256];
/* Create the thread creating the I/O for the given file. */
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;
}
}
}
}
}
else
rc = VERR_NO_MEMORY;
}
else
rc = VERR_NO_MEMORY;
return rc;
}
/**
* Closes a test file.
*
* @returns nothing.
* @param pTestFile Pointer to the test file.
*/
{
int rcThread;
int rc;
RTPrintf("Terminating I/O thread, please wait...\n");
/* Let the thread know that it should terminate. */
/* Wait for the thread to terminate. */
/* Free resources */
}
/**
* Inits the test pattern.
*
* @returns VBox status code.
*/
static int tstPDMACStressTestPatternInit(void)
{
if (!g_pbTestPattern)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
}
static void tstPDMACStressTestPatternDestroy(void)
{
}
{
int rcRet = 0; /* error count */
int rc = VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
/*
* Little hack to avoid the VM_ASSERT_EMT assertion.
*/
if (RT_SUCCESS(rc))
{
unsigned cFilesOpened = 0;
/* Open the endpoints. */
{
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");
}
/* Close opened endpoints. */
for (unsigned i = 0; i < cFilesOpened; i++)
}
else
{
rcRet++;
}
}
else
{
rcRet++;
}
return rcRet;
}