~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to src/VBox/VMM/testcase/tstPDMAsyncCompletionStress.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: tstPDMAsyncCompletionStress.cpp $ */
 
2
/** @file
 
3
 * PDM Asynchronous Completion Stresstest.
 
4
 *
 
5
 * This testcase is for stress testing the async completion interface.
 
6
 */
 
7
 
 
8
/*
 
9
 * Copyright (C) 2008-2009 Sun Microsystems, Inc.
 
10
 *
 
11
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
12
 * available from http://www.virtualbox.org. This file is free software;
 
13
 * you can redistribute it and/or modify it under the terms of the GNU
 
14
 * General Public License (GPL) as published by the Free Software
 
15
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
16
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
17
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
18
 *
 
19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 
20
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 
21
 * additional information or have any questions.
 
22
 */
 
23
 
 
24
/*******************************************************************************
 
25
*   Header Files                                                               *
 
26
*******************************************************************************/
 
27
#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
 
28
 
 
29
#include "../VMInternal.h" /* UVM */
 
30
#include <VBox/vm.h>
 
31
#include <VBox/uvm.h>
 
32
#include <VBox/pdmasynccompletion.h>
 
33
#include <VBox/vmm.h>
 
34
#include <VBox/cpum.h>
 
35
#include <VBox/err.h>
 
36
#include <VBox/log.h>
 
37
#include <VBox/pdmapi.h>
 
38
#include <VBox/pdmthread.h>
 
39
#include <iprt/alloc.h>
 
40
#include <iprt/asm.h>
 
41
#include <iprt/assert.h>
 
42
#include <iprt/file.h>
 
43
#include <iprt/initterm.h>
 
44
#include <iprt/semaphore.h>
 
45
#include <iprt/rand.h>
 
46
#include <iprt/string.h>
 
47
#include <iprt/path.h>
 
48
#include <iprt/stream.h>
 
49
#include <iprt/thread.h>
 
50
#include <iprt/param.h>
 
51
 
 
52
#define TESTCASE "tstPDMAsyncCompletionStress"
 
53
 
 
54
#if 0
 
55
/** Number of simultaneous open endpoints for reading and writing. */
 
56
#define NR_OPEN_ENDPOINTS 10
 
57
/** Test pattern size. */
 
58
#define TEST_PATTERN_SIZE (100*_1M)
 
59
/** Minimum file size. */
 
60
#define FILE_SIZE_MIN (100 * _1M)
 
61
/** Maximum file size. */
 
62
#define FILE_SIZE_MAX (10000UL * _1M)
 
63
/** Minimum segment size. */
 
64
#define SEGMENT_SIZE_MIN (512)
 
65
/** Maximum segment size. */
 
66
#define SEGMENT_SIZE_MAX (TEST_PATTERN_SIZE)
 
67
/** Maximum number of active tasks. */
 
68
#define TASK_ACTIVE_MAX (1024)
 
69
/** Maximum size of a transfer. */
 
70
#define TASK_TRANSFER_SIZE_MAX (10*_1M)
 
71
#else
 
72
/** Number of simultaneous open endpoints for reading and writing. */
 
73
#define NR_OPEN_ENDPOINTS 5
 
74
/** Test pattern size. */
 
75
#define TEST_PATTERN_SIZE (10*_1M)
 
76
/** Minimum file size. */
 
77
#define FILE_SIZE_MIN (100 * _1M)
 
78
/** Maximum file size. */
 
79
#define FILE_SIZE_MAX (1000UL * _1M)
 
80
/** Minimum segment size. */
 
81
#define SEGMENT_SIZE_MIN (512)
 
82
/** Maximum segment size. */
 
83
#define SEGMENT_SIZE_MAX (TEST_PATTERN_SIZE)
 
84
/** Maximum number of active tasks. */
 
85
#define TASK_ACTIVE_MAX (1)
 
86
/** Maximum size of a transfer. */
 
87
#define TASK_TRANSFER_SIZE_MAX (_1M)
 
88
#endif
 
89
 
 
90
/**
 
91
 * Structure defining a file segment.
 
92
 */
 
93
typedef struct PDMACTESTFILESEG
 
94
{
 
95
    /** Start offset in the file. */
 
96
    RTFOFF                     off;
 
97
    /** Size of the segment. */
 
98
    size_t                     cbSegment;
 
99
    /** Pointer to the start of the data in the test pattern used for the segment. */
 
100
    uint8_t                   *pbData;
 
101
} PDMACTESTFILESEG, *PPDMACTESTFILESEG;
 
102
 
 
103
/**
 
104
 * Structure defining a I/O task.
 
105
 */
 
106
typedef struct PDMACTESTFILETASK
 
107
{
 
108
    /** Flag whether the task is currently active. */
 
109
    bool                        fActive;
 
110
    /** Flag whether this is a write. */
 
111
    bool                        fWrite;
 
112
    /** Start offset. */
 
113
    RTFOFF                      off;
 
114
    /** Data segment */
 
115
    PDMDATASEG                  DataSeg;
 
116
    /** Task handle. */
 
117
    PPDMASYNCCOMPLETIONTASK     hTask;
 
118
} PDMACTESTFILETASK, *PPDMACTESTFILETASK;
 
119
 
 
120
/**
 
121
 * Structure defining a test file.
 
122
 */
 
123
typedef struct PDMACTESTFILE
 
124
{
 
125
    /** The PDM async completion endpoint handle. */
 
126
    PPDMASYNCCOMPLETIONENDPOINT hEndpoint;
 
127
    /** Template used for this file. */
 
128
    PPDMASYNCCOMPLETIONTEMPLATE pTemplate;
 
129
    /** Maximum size of the file. */
 
130
    uint64_t                   cbFileMax;
 
131
    /** Current size of the file. */
 
132
    uint64_t                   cbFileCurr;
 
133
    /** Size of a file segment. */
 
134
    size_t                     cbFileSegment;
 
135
    /** Maximum number of segments. */
 
136
    unsigned                   cSegments;
 
137
    /** Pointer to the array describing how the file is assembled
 
138
     * of the test pattern. Used for comparing read data to ensure
 
139
     * that no corruption occured.
 
140
     */
 
141
    PPDMACTESTFILESEG          paSegs;
 
142
    /** Maximum number of active tasks for this endpoint. */
 
143
    uint32_t                   cTasksActiveMax;
 
144
    /** Number of current active tasks. */
 
145
    volatile uint32_t          cTasksActiveCurr;
 
146
    /** Pointer to the array of task. */
 
147
    PPDMACTESTFILETASK         paTasks;
 
148
    /** I/O thread handle. */
 
149
    PPDMTHREAD                 hThread;
 
150
    /** Flag whether the thread should terminate. */
 
151
    bool                       fRunning;
 
152
} PDMACTESTFILE, *PPDMACTESTFILE;
 
153
 
 
154
/** Buffer storing the random test pattern. */
 
155
uint8_t *g_pbTestPattern = NULL;
 
156
/** Size of the test pattern. */
 
157
size_t   g_cbTestPattern;
 
158
/** Array holding test files. */
 
159
PDMACTESTFILE g_aTestFiles[NR_OPEN_ENDPOINTS];
 
160
 
 
161
static void tstPDMACStressTestFileVerify(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
 
162
{
 
163
    size_t   cbLeft = pTestTask->DataSeg.cbSeg;
 
164
    RTFOFF   off    = pTestTask->off;
 
165
    uint8_t *pbBuf  = (uint8_t *)pTestTask->DataSeg.pvSeg;
 
166
 
 
167
    while (cbLeft)
 
168
    {
 
169
        size_t cbCompare;
 
170
        unsigned iSeg = off / pTestFile->cbFileSegment;
 
171
        PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[iSeg];
 
172
        uint8_t *pbTestPattern;
 
173
        unsigned offSeg = off - pSeg->off;
 
174
 
 
175
        cbCompare = RT_MIN(cbLeft, pSeg->cbSegment - offSeg);
 
176
        pbTestPattern = pSeg->pbData + offSeg;
 
177
 
 
178
        if (memcmp(pbBuf, pbTestPattern, cbCompare))
 
179
            AssertMsgFailed(("Unexpected data for off=%RTfoff size=%u\n", pTestTask->off, pTestTask->DataSeg.cbSeg));
 
180
 
 
181
        pbBuf  += cbCompare;
 
182
        off    += cbCompare;
 
183
        cbLeft -= cbCompare;
 
184
    }
 
185
}
 
186
 
 
187
static void tstPDMACStressTestFileFillBuffer(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
 
188
{
 
189
    uint8_t *pbBuf = (uint8_t *)pTestTask->DataSeg.pvSeg;
 
190
    size_t  cbLeft = pTestTask->DataSeg.cbSeg;
 
191
    RTFOFF  off    = pTestTask->off;
 
192
 
 
193
    Assert(pTestTask->fWrite && pTestTask->fActive);
 
194
 
 
195
    while (cbLeft)
 
196
    {
 
197
        size_t cbFill;
 
198
        unsigned iSeg = off / pTestFile->cbFileSegment;
 
199
        PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[iSeg];
 
200
        uint8_t *pbTestPattern;
 
201
        unsigned offSeg = off - pSeg->off;
 
202
 
 
203
        cbFill = RT_MIN(cbLeft, pSeg->cbSegment - offSeg);
 
204
        pbTestPattern = pSeg->pbData + offSeg;
 
205
 
 
206
        memcpy(pbBuf, pbTestPattern, cbFill);
 
207
 
 
208
        pbBuf  += cbFill;
 
209
        off    += cbFill;
 
210
        cbLeft -= cbFill;
 
211
    }
 
212
}
 
213
 
 
214
static int tstPDMACStressTestFileWrite(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
 
215
{
 
216
    int rc = VINF_SUCCESS;
 
217
 
 
218
    Assert(!pTestTask->fActive);
 
219
 
 
220
    pTestTask->fActive       = true;
 
221
    pTestTask->fWrite        = true;
 
222
    pTestTask->DataSeg.cbSeg = RTRandU32Ex(512, TASK_TRANSFER_SIZE_MAX) & ~511;
 
223
 
 
224
    uint64_t offMax;
 
225
 
 
226
    /* Did we reached the maximum file size */
 
227
    if (pTestFile->cbFileCurr < pTestFile->cbFileMax)
 
228
    {
 
229
        offMax =   (pTestFile->cbFileMax - pTestFile->cbFileCurr) < pTestTask->DataSeg.cbSeg
 
230
                 ? pTestFile->cbFileMax - pTestTask->DataSeg.cbSeg
 
231
                 : pTestFile->cbFileCurr;
 
232
    }
 
233
    else
 
234
        offMax = pTestFile->cbFileMax - pTestTask->DataSeg.cbSeg;
 
235
 
 
236
    uint64_t offMin;
 
237
 
 
238
    /*
 
239
     * If we reached the maximum file size write in the whole file
 
240
     * otherwise we will enforce the range for random offsets to let it grow
 
241
     * more quickly.
 
242
     */
 
243
    if (pTestFile->cbFileCurr == pTestFile->cbFileMax)
 
244
        offMin = 0;
 
245
    else
 
246
        offMin = RT_MIN(pTestFile->cbFileCurr, offMax);
 
247
 
 
248
 
 
249
    pTestTask->off = RTRandU64Ex(offMin, offMax) & ~511;
 
250
 
 
251
    /* Set new file size of required */
 
252
    if ((uint64_t)pTestTask->off + pTestTask->DataSeg.cbSeg > pTestFile->cbFileCurr)
 
253
        pTestFile->cbFileCurr = pTestTask->off + pTestTask->DataSeg.cbSeg;
 
254
 
 
255
    AssertMsg(pTestFile->cbFileCurr <= pTestFile->cbFileMax,
 
256
              ("Current file size (%llu) exceeds final size (%llu)\n",
 
257
              pTestFile->cbFileCurr, pTestFile->cbFileMax));
 
258
 
 
259
    /* Allocate data buffer. */
 
260
    pTestTask->DataSeg.pvSeg = RTMemAlloc(pTestTask->DataSeg.cbSeg);
 
261
    if (!pTestTask->DataSeg.pvSeg)
 
262
        return VERR_NO_MEMORY;
 
263
 
 
264
    /* Fill data into buffer. */
 
265
    tstPDMACStressTestFileFillBuffer(pTestFile, pTestTask);
 
266
 
 
267
    /* Engage */
 
268
    rc = PDMR3AsyncCompletionEpWrite(pTestFile->hEndpoint, pTestTask->off,
 
269
                                     &pTestTask->DataSeg, 1,
 
270
                                     pTestTask->DataSeg.cbSeg,
 
271
                                     pTestTask,
 
272
                                     &pTestTask->hTask);
 
273
 
 
274
    return rc;
 
275
}
 
276
 
 
277
static int tstPDMACStressTestFileRead(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
 
278
{
 
279
    int rc = VINF_SUCCESS;
 
280
 
 
281
    Assert(!pTestTask->fActive);
 
282
 
 
283
    pTestTask->fActive       = true;
 
284
    pTestTask->fWrite        = false;
 
285
    pTestTask->DataSeg.cbSeg = RTRandU32Ex(1, RT_MIN(pTestFile->cbFileCurr, TASK_TRANSFER_SIZE_MAX));
 
286
 
 
287
    AssertMsg(pTestFile->cbFileCurr >= pTestTask->DataSeg.cbSeg, ("Impossible\n"));
 
288
    pTestTask->off = RTRandU64Ex(0, pTestFile->cbFileCurr - pTestTask->DataSeg.cbSeg);
 
289
 
 
290
    /* Allocate data buffer. */
 
291
    pTestTask->DataSeg.pvSeg = RTMemAlloc(pTestTask->DataSeg.cbSeg);
 
292
    if (!pTestTask->DataSeg.pvSeg)
 
293
        return VERR_NO_MEMORY;
 
294
 
 
295
    /* Engage */
 
296
    rc = PDMR3AsyncCompletionEpRead(pTestFile->hEndpoint, pTestTask->off,
 
297
                                     &pTestTask->DataSeg, 1,
 
298
                                     pTestTask->DataSeg.cbSeg,
 
299
                                     pTestTask,
 
300
                                     &pTestTask->hTask);
 
301
 
 
302
    return rc;
 
303
}
 
304
 
 
305
/**
 
306
 * Returns true with the given chance in percent.
 
307
 *
 
308
 * @returns true or false
 
309
 * @param   iPercentage   The percentage of the chance to return true.
 
310
 */
 
311
static bool tstPDMACTestIsTrue(int iPercentage)
 
312
{
 
313
    int uRnd = RTRandU32Ex(0, 100);
 
314
 
 
315
    return (uRnd < iPercentage); /* This should be enough for our purpose */
 
316
}
 
317
 
 
318
static int tstPDMACTestFileThread(PVM pVM, PPDMTHREAD pThread)
 
319
{
 
320
    PPDMACTESTFILE pTestFile = (PPDMACTESTFILE)pThread->pvUser;
 
321
    int iWriteChance = 100; /* Chance to get a write task in percent. */
 
322
    uint32_t cTasksStarted = 0;
 
323
    int rc = VINF_SUCCESS;
 
324
 
 
325
    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
 
326
        return VINF_SUCCESS;
 
327
 
 
328
    while (pTestFile->fRunning)
 
329
    {
 
330
        unsigned iTaskCurr = 0;
 
331
 
 
332
 
 
333
        /* Fill all tasks */
 
334
        while (   (pTestFile->cTasksActiveCurr < pTestFile->cTasksActiveMax)
 
335
               && (iTaskCurr < pTestFile->cTasksActiveMax))
 
336
        {
 
337
            PPDMACTESTFILETASK pTask = &pTestFile->paTasks[iTaskCurr];
 
338
 
 
339
            if (!pTask->fActive)
 
340
            {
 
341
                /* Read or write task? */
 
342
                bool fWrite = tstPDMACTestIsTrue(iWriteChance);
 
343
 
 
344
                ASMAtomicIncU32(&pTestFile->cTasksActiveCurr);
 
345
 
 
346
                if (fWrite)
 
347
                    rc = tstPDMACStressTestFileWrite(pTestFile, pTask);
 
348
                else
 
349
                    rc = tstPDMACStressTestFileRead(pTestFile, pTask);
 
350
 
 
351
                AssertRC(rc);
 
352
 
 
353
                cTasksStarted++;
 
354
            }
 
355
 
 
356
            iTaskCurr++;
 
357
        }
 
358
 
 
359
        /*
 
360
         * Recalc write chance. The bigger the file the lower the chance to have a write.
 
361
         * The minimum chance is 33 percent.
 
362
         */
 
363
        iWriteChance = 100 - (int)(((float)100.0 / pTestFile->cbFileMax) * (float)pTestFile->cbFileCurr);
 
364
        iWriteChance = RT_MAX(33, iWriteChance);
 
365
 
 
366
        /* Wait a random amount of time. (1ms - 100ms) */
 
367
        RTThreadSleep(RTRandU32Ex(1, 100));
 
368
    }
 
369
 
 
370
    /* Wait for the rest to complete. */
 
371
    while (pTestFile->cTasksActiveCurr)
 
372
        RTThreadSleep(250);
 
373
 
 
374
    RTPrintf("Thread exiting: processed %u tasks\n", cTasksStarted);
 
375
    return rc;
 
376
}
 
377
 
 
378
static void tstPDMACStressTestFileTaskCompleted(PVM pVM, void *pvUser, void *pvUser2)
 
379
{
 
380
    PPDMACTESTFILE pTestFile = (PPDMACTESTFILE)pvUser2;
 
381
    PPDMACTESTFILETASK pTestTask = (PPDMACTESTFILETASK)pvUser;
 
382
 
 
383
    if (pTestTask->fWrite)
 
384
    {
 
385
        /* @todo Do something sensible here. */
 
386
    }
 
387
    else
 
388
    {
 
389
        tstPDMACStressTestFileVerify(pTestFile, pTestTask); /* Will assert if it fails */
 
390
    }
 
391
 
 
392
    RTMemFree(pTestTask->DataSeg.pvSeg);
 
393
    pTestTask->fActive = false;
 
394
    AssertMsg(pTestFile->cTasksActiveCurr > 0, ("Trying to complete a non active task\n"));
 
395
    ASMAtomicDecU32(&pTestFile->cTasksActiveCurr);
 
396
}
 
397
 
 
398
/**
 
399
 * Sets up a test file creating the I/O thread.
 
400
 *
 
401
 * @returns VBox status code.
 
402
 * @param   pVM          Pointer to the shared VM instance structure.
 
403
 * @param   pTestFile    Pointer to the uninitialized test file structure.
 
404
 * @param   iTestId      Unique test id.
 
405
 */
 
406
static int tstPDMACStressTestFileOpen(PVM pVM, PPDMACTESTFILE pTestFile, unsigned iTestId)
 
407
{
 
408
    int rc = VERR_NO_MEMORY;
 
409
 
 
410
    /* Size is a multiple of 512 */
 
411
    pTestFile->cbFileMax     = RTRandU64Ex(FILE_SIZE_MIN, FILE_SIZE_MAX) & ~(511UL);
 
412
    pTestFile->cbFileCurr    = 0;
 
413
    pTestFile->cbFileSegment = RTRandU32Ex(SEGMENT_SIZE_MIN, RT_MIN(pTestFile->cbFileMax, SEGMENT_SIZE_MAX)) & ~((size_t)511);
 
414
 
 
415
    Assert(pTestFile->cbFileMax >= pTestFile->cbFileSegment);
 
416
 
 
417
    /* Set up the segments array. */
 
418
    pTestFile->cSegments  = pTestFile->cbFileMax / pTestFile->cbFileSegment;
 
419
    pTestFile->cSegments += ((pTestFile->cbFileMax % pTestFile->cbFileSegment) > 0) ? 1 : 0;
 
420
 
 
421
    pTestFile->paSegs = (PPDMACTESTFILESEG)RTMemAllocZ(pTestFile->cSegments * sizeof(PDMACTESTFILESEG));
 
422
    if (pTestFile->paSegs)
 
423
    {
 
424
        /* Init the segments */
 
425
        for (unsigned i = 0; i < pTestFile->cSegments; i++)
 
426
        {
 
427
            PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[i];
 
428
 
 
429
            pSeg->off       = (RTFOFF)i * pTestFile->cbFileSegment;
 
430
            pSeg->cbSegment = pTestFile->cbFileSegment;
 
431
 
 
432
            /* Let the buffer point to a random position in the test pattern. */
 
433
            uint32_t offTestPattern = RTRandU64Ex(0, g_cbTestPattern - pSeg->cbSegment);
 
434
 
 
435
            pSeg->pbData = g_pbTestPattern + offTestPattern;
 
436
        }
 
437
 
 
438
        /* Init task array. */
 
439
        pTestFile->cTasksActiveMax = RTRandU32Ex(1, TASK_ACTIVE_MAX);
 
440
        pTestFile->paTasks         = (PPDMACTESTFILETASK)RTMemAllocZ(pTestFile->cTasksActiveMax * sizeof(PDMACTESTFILETASK));
 
441
        if (pTestFile->paTasks)
 
442
        {
 
443
            /* Create the template */
 
444
            char szDesc[256];
 
445
 
 
446
            RTStrPrintf(szDesc, sizeof(szDesc), "Template-%d", iTestId);
 
447
            rc = PDMR3AsyncCompletionTemplateCreateInternal(pVM, &pTestFile->pTemplate, tstPDMACStressTestFileTaskCompleted, pTestFile, szDesc);
 
448
            if (RT_SUCCESS(rc))
 
449
            {
 
450
                /* Open the endpoint now. Because async completion endpoints cannot create files we have to do it before. */
 
451
                char szFile[RTPATH_MAX];
 
452
 
 
453
                RTStrPrintf(szFile, sizeof(szFile), "tstPDMAsyncCompletionStress-%d.tmp", iTestId);
 
454
 
 
455
                RTFILE FileTmp;
 
456
                rc = RTFileOpen(&FileTmp, szFile, RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_NONE);
 
457
                if (RT_SUCCESS(rc))
 
458
                {
 
459
                    RTFileClose(FileTmp);
 
460
 
 
461
                    rc = PDMR3AsyncCompletionEpCreateForFile(&pTestFile->hEndpoint, szFile, PDMACEP_FILE_FLAGS_CACHING, pTestFile->pTemplate);
 
462
                    if (RT_SUCCESS(rc))
 
463
                    {
 
464
                        char szThreadDesc[256];
 
465
 
 
466
                        pTestFile->fRunning = true;
 
467
 
 
468
                        /* Create the thread creating the I/O for the given file. */
 
469
                        RTStrPrintf(szThreadDesc, sizeof(szThreadDesc), "PDMACThread-%d", iTestId);
 
470
                        rc = PDMR3ThreadCreate(pVM, &pTestFile->hThread, pTestFile, tstPDMACTestFileThread,
 
471
                                               NULL, 0, RTTHREADTYPE_IO, szThreadDesc);
 
472
                        if (RT_SUCCESS(rc))
 
473
                        {
 
474
                            rc = PDMR3ThreadResume(pTestFile->hThread);
 
475
                            AssertRC(rc);
 
476
 
 
477
                            RTPrintf(TESTCASE ": Created test file %s cbFileMax=%llu cbFileSegment=%u cSegments=%u cTasksActiveMax=%u\n",
 
478
                                     szFile, pTestFile->cbFileMax, pTestFile->cbFileSegment, pTestFile->cSegments, pTestFile->cTasksActiveMax);
 
479
                            return VINF_SUCCESS;
 
480
                        }
 
481
 
 
482
                        PDMR3AsyncCompletionEpClose(pTestFile->hEndpoint);
 
483
                    }
 
484
 
 
485
                    RTFileDelete(szFile);
 
486
                }
 
487
 
 
488
                PDMR3AsyncCompletionTemplateDestroy(pTestFile->pTemplate);
 
489
            }
 
490
 
 
491
            RTMemFree(pTestFile->paTasks);
 
492
        }
 
493
        else
 
494
            rc = VERR_NO_MEMORY;
 
495
 
 
496
        RTMemFree(pTestFile->paSegs);
 
497
    }
 
498
    else
 
499
        rc = VERR_NO_MEMORY;
 
500
 
 
501
    RTPrintf(TESTCASE ": Opening test file with id %d failed rc=%Rrc\n", iTestId, rc);
 
502
 
 
503
    return rc;
 
504
}
 
505
 
 
506
/**
 
507
 * Closes a test file.
 
508
 *
 
509
 * @returns nothing.
 
510
 * @param pTestFile    Pointer to the test file.
 
511
 */
 
512
static void tstPDMACStressTestFileClose(PPDMACTESTFILE pTestFile)
 
513
{
 
514
    int rcThread;
 
515
    int rc;
 
516
 
 
517
    RTPrintf("Terminating I/O thread, please wait...\n");
 
518
 
 
519
    /* Let the thread know that it should terminate. */
 
520
    pTestFile->fRunning = false;
 
521
 
 
522
    /* Wait for the thread to terminate. */
 
523
    rc = PDMR3ThreadDestroy(pTestFile->hThread, &rcThread);
 
524
 
 
525
    RTPrintf("Thread terminated with status code rc=%Rrc\n", rcThread);
 
526
 
 
527
    /* Free resources */
 
528
    RTMemFree(pTestFile->paTasks);
 
529
    RTMemFree(pTestFile->paSegs);
 
530
    PDMR3AsyncCompletionEpClose(pTestFile->hEndpoint);
 
531
    PDMR3AsyncCompletionTemplateDestroy(pTestFile->pTemplate);
 
532
}
 
533
 
 
534
/**
 
535
 * Inits the test pattern.
 
536
 *
 
537
 * @returns VBox status code.
 
538
 */
 
539
static int tstPDMACStressTestPatternInit(void)
 
540
{
 
541
    RTPrintf(TESTCASE ": Creating test pattern. Please wait...\n");
 
542
    g_cbTestPattern = TEST_PATTERN_SIZE;
 
543
    g_pbTestPattern = (uint8_t *)RTMemAlloc(g_cbTestPattern);
 
544
    if (!g_pbTestPattern)
 
545
        return VERR_NO_MEMORY;
 
546
 
 
547
    RTRandBytes(g_pbTestPattern, g_cbTestPattern);
 
548
    return VINF_SUCCESS;
 
549
}
 
550
 
 
551
static void tstPDMACStressTestPatternDestroy(void)
 
552
{
 
553
    RTPrintf(TESTCASE ": Destroying test pattern\n");
 
554
    RTMemFree(g_pbTestPattern);
 
555
}
 
556
 
 
557
int main(int argc, char *argv[])
 
558
{
 
559
    int rcRet = 0; /* error count */
 
560
    int rc = VINF_SUCCESS;
 
561
 
 
562
    RTR3InitAndSUPLib();
 
563
 
 
564
    PVM pVM;
 
565
    rc = VMR3Create(1, NULL, NULL, NULL, NULL, &pVM);
 
566
    if (RT_SUCCESS(rc))
 
567
    {
 
568
        /*
 
569
         * Little hack to avoid the VM_ASSERT_EMT assertion.
 
570
         */
 
571
        RTTlsSet(pVM->pUVM->vm.s.idxTLS, &pVM->pUVM->aCpus[0]);
 
572
        pVM->pUVM->aCpus[0].pUVM = pVM->pUVM;
 
573
        pVM->pUVM->aCpus[0].vm.s.NativeThreadEMT = RTThreadNativeSelf();
 
574
 
 
575
        rc = tstPDMACStressTestPatternInit();
 
576
        if (RT_SUCCESS(rc))
 
577
        {
 
578
            unsigned cFilesOpened = 0;
 
579
 
 
580
            /* Open the endpoints. */
 
581
            for (cFilesOpened = 0; cFilesOpened < NR_OPEN_ENDPOINTS; cFilesOpened++)
 
582
            {
 
583
                rc = tstPDMACStressTestFileOpen(pVM, &g_aTestFiles[cFilesOpened], cFilesOpened);
 
584
                if (RT_FAILURE(rc))
 
585
                    break;
 
586
            }
 
587
 
 
588
            if (RT_SUCCESS(rc))
 
589
            {
 
590
                /* Tests are running now. */
 
591
                RTPrintf(TESTCASE ": Successfully opened all files. Running tests forever now or until an error is hit :)\n");
 
592
                RTThreadSleep(RT_INDEFINITE_WAIT);
 
593
            }
 
594
 
 
595
            /* Close opened endpoints. */
 
596
            for (unsigned i = 0; i < cFilesOpened; i++)
 
597
                tstPDMACStressTestFileClose(&g_aTestFiles[i]);
 
598
 
 
599
            tstPDMACStressTestPatternDestroy();
 
600
        }
 
601
        else
 
602
        {
 
603
            RTPrintf(TESTCASE ": failed to init test pattern!! rc=%Rrc\n", rc);
 
604
            rcRet++;
 
605
        }
 
606
 
 
607
        rc = VMR3Destroy(pVM);
 
608
        AssertMsg(rc == VINF_SUCCESS, ("%s: Destroying VM failed rc=%Rrc!!\n", __FUNCTION__, rc));
 
609
    }
 
610
    else
 
611
    {
 
612
        RTPrintf(TESTCASE ": failed to create VM!! rc=%Rrc\n", rc);
 
613
        rcRet++;
 
614
    }
 
615
 
 
616
    return rcRet;
 
617
}
 
618