VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstPDMAsyncCompletionStress.cpp@ 105770

Last change on this file since 105770 was 99739, checked in by vboxsync, 19 months ago

*: doxygen corrections (mostly about removing @returns from functions returning void).

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette