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