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