Changeset 26338 in vbox
- Timestamp:
- Feb 9, 2010 12:54:20 AM (15 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
-
PDMAsyncCompletionFile.cpp (modified) (3 diffs)
-
PDMAsyncCompletionFileInternal.h (modified) (9 diffs)
-
PDMAsyncCompletionFileNormal.cpp (modified) (6 diffs)
-
testcase/tstPDMAsyncCompletionStress.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp
r26147 r26338 738 738 } 739 739 740 pEpFile->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE; 741 742 /* Assign the endpoint to the thread. */ 743 rc = pdmacFileAioMgrAddEndpoint(pAioMgr, pEpFile); 744 if (RT_FAILURE(rc)) 745 MMR3HeapFree(pEpFile->pTasksFreeHead); 740 pEpFile->AioMgr.pTreeRangesLocked = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE)); 741 if (!pEpFile->AioMgr.pTreeRangesLocked) 742 rc = VERR_NO_MEMORY; 743 else 744 { 745 pEpFile->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE; 746 747 /* Assign the endpoint to the thread. */ 748 rc = pdmacFileAioMgrAddEndpoint(pAioMgr, pEpFile); 749 if (RT_FAILURE(rc)) 750 { 751 RTMemFree(pEpFile->AioMgr.pTreeRangesLocked); 752 MMR3HeapFree(pEpFile->pTasksFreeHead); 753 } 754 } 746 755 } 747 756 } … … 767 776 768 777 return rc; 778 } 779 780 static int pdmacFileEpRangesLockedDestroy(PAVLRFOFFNODECORE pNode, void *pvUser) 781 { 782 AssertMsgFailed(("The locked ranges tree should be empty at that point\n")); 783 return VINF_SUCCESS; 769 784 } 770 785 … … 798 813 if (pEpFile->fCaching) 799 814 pdmacFileEpCacheDestroy(pEpFile); 815 816 /* Destroy the locked ranges tree now. */ 817 RTAvlrFileOffsetDestroy(pEpFile->AioMgr.pTreeRangesLocked, pdmacFileEpRangesLockedDestroy, NULL); 800 818 801 819 RTFileClose(pEpFile->File); -
trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h
r26334 r26338 34 34 #include "PDMAsyncCompletionInternal.h" 35 35 36 /** Enable the 2Q cache alogrithm. */37 #define VBOX_WITH_2Q_CACHE 138 39 36 /** @todo: Revise the caching of tasks. We have currently four caches: 40 37 * Per endpoint task cache … … 61 58 /** Pointer to the global cache structure. */ 62 59 typedef struct PDMACFILECACHEGLOBAL *PPDMACFILECACHEGLOBAL; 60 /** Pointer to a task segment. */ 61 typedef struct PDMACFILETASKSEG *PPDMACFILETASKSEG; 63 62 64 63 /** … … 189 188 190 189 /** 190 * A file access range lock. 191 */ 192 typedef struct PDMACFILERANGELOCK 193 { 194 /** AVL node in the locked range tree of the endpoint. */ 195 AVLRFOFFNODECORE Core; 196 /** How many tasks have locked this range. */ 197 uint32_t cRefs; 198 /** Flag whether this is a read or write lock. */ 199 bool fReadLock; 200 /** List of tasks which are waiting that the range gets unlocked. */ 201 PPDMACTASKFILE pWaitingTasksHead; 202 /** List of tasks which are waiting that the range gets unlocked. */ 203 PPDMACTASKFILE pWaitingTasksTail; 204 } PDMACFILERANGELOCK, *PPDMACFILERANGELOCK; 205 206 /** 191 207 * Data for one request segment waiting for cache entry. 192 208 */ … … 205 221 /** Flag whether this entry writes data to the cache. */ 206 222 bool fWrite; 207 } PDMACFILETASKSEG , *PPDMACFILETASKSEG;223 } PDMACFILETASKSEG; 208 224 209 225 /** … … 260 276 { 261 277 /** Head of the list. */ 262 PPDMACFILECACHEENTRY pHead;278 PPDMACFILECACHEENTRY pHead; 263 279 /** Tail of the list. */ 264 PPDMACFILECACHEENTRY pTail;280 PPDMACFILECACHEENTRY pTail; 265 281 /** Number of bytes cached in the list. */ 266 uint32_t cbCached;282 uint32_t cbCached; 267 283 } PDMACFILELRULIST; 268 284 … … 278 294 /** Critical section protecting the cache. */ 279 295 RTCRITSECT CritSect; 280 #ifdef VBOX_WITH_2Q_CACHE281 296 uint32_t cbRecentlyUsedInMax; 282 297 uint32_t cbRecentlyUsedOutMax; … … 284 299 PDMACFILELRULIST LruRecentlyUsedOut; 285 300 PDMACFILELRULIST LruFrequentlyUsed; 286 #else287 /** Adaption parameter (p) */288 uint32_t uAdaptVal;289 /** LRU list for recently used entries (T1) */290 PDMACFILELRULIST LruRecentlyUsed;291 /** LRU list for frequently used entries (T2) */292 PDMACFILELRULIST LruFrequentlyUsed;293 /** LRU list for recently evicted entries (B1) */294 PDMACFILELRULIST LruRecentlyGhost;295 /** LRU list for evicted entries from T2 (B2) */296 PDMACFILELRULIST LruFrequentlyGhost;297 #endif298 301 #ifdef VBOX_WITH_STATISTICS 299 302 /** Hit counter. */ … … 486 489 /** Tail of pending requests. */ 487 490 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingTail; 491 /** Tree of currently locked ranges. 492 * If a write task is enqueued the range gets locked and any other 493 * task writing to that range has to wait until the task completes. 494 */ 495 PAVLRFOFFTREE pTreeRangesLocked; 488 496 /** Number of requests currently being processed for this endpoint 489 497 * (excluded flush requests). */ … … 527 535 typedef struct PDMACTASKFILE 528 536 { 529 /** next task in the list. */ 537 /** Pointer to the range lock we are waiting for */ 538 PPDMACFILERANGELOCK pRangeLock; 539 /** Next task in the list. (Depending on the state) */ 530 540 struct PDMACTASKFILE *pNext; 531 541 /** Endpoint */ -
trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp
r26147 r26338 36 36 #define PDMACEPFILEMGR_REQS_MAX 512 /* @todo: Find better solution wrt. the request number*/ 37 37 38 /******************************************************************************* 39 * Internal functions * 40 *******************************************************************************/ 41 static int pdmacFileAioMgrNormalProcessTaskList(PPDMACTASKFILE pTaskHead, 42 PPDMACEPFILEMGR pAioMgr, 43 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint); 44 45 38 46 int pdmacFileAioMgrNormalInit(PPDMACEPFILEMGR pAioMgr) 39 47 { … … 399 407 } 400 408 409 /** 410 * Allocates a async I/O request. 411 * 412 * @returns Handle to the request. 413 * @param pAioMgr The I/O manager. 414 */ 415 static RTFILEAIOREQ pdmacFileAioMgrNormalRequestAlloc(PPDMACEPFILEMGR pAioMgr) 416 { 417 RTFILEAIOREQ hReq = NIL_RTFILEAIOREQ; 418 419 /* Get a request handle. */ 420 if (pAioMgr->iFreeReqNext != pAioMgr->iFreeEntryNext) 421 { 422 hReq = pAioMgr->pahReqsFree[pAioMgr->iFreeReqNext]; 423 pAioMgr->pahReqsFree[pAioMgr->iFreeReqNext] = NIL_RTFILEAIOREQ; 424 pAioMgr->iFreeReqNext = (pAioMgr->iFreeReqNext + 1) % pAioMgr->cReqEntries; 425 } 426 else 427 { 428 int rc = RTFileAioReqCreate(&hReq); 429 AssertRC(rc); 430 } 431 432 return hReq; 433 } 434 435 static bool pdmacFileAioMgrNormalIsRangeLocked(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, 436 RTFOFF offStart, size_t cbRange, 437 PPDMACTASKFILE pTask) 438 { 439 PPDMACFILERANGELOCK pRangeLock = NULL; /** < Range lock */ 440 441 AssertMsg( pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE 442 || pTask->enmTransferType == PDMACTASKFILETRANSFER_READ, 443 ("Invalid task type %d\n", pTask->enmTransferType)); 444 445 pRangeLock = (PPDMACFILERANGELOCK)RTAvlrFileOffsetGet(pEndpoint->AioMgr.pTreeRangesLocked, offStart); 446 if (!pRangeLock) 447 { 448 pRangeLock = (PPDMACFILERANGELOCK)RTAvlrFileOffsetGetBestFit(pEndpoint->AioMgr.pTreeRangesLocked, offStart, true); 449 /* Check if we intersect with the range. */ 450 if ( !pRangeLock 451 || !( (pRangeLock->Core.Key) <= (offStart + (RTFOFF)cbRange - 1) 452 && (pRangeLock->Core.KeyLast) >= offStart)) 453 { 454 pRangeLock = NULL; /* False alarm */ 455 } 456 } 457 458 /* Check whether we have one of the situations explained below */ 459 if ( pRangeLock 460 #if 0 /** @todo: later. For now we will just block all requests if they interfere */ 461 && ( (pRangeLock->fReadLock && pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE) 462 || (!pRangeLock->fReadLock) 463 #endif 464 ) 465 { 466 /* Add to the list. */ 467 pTask->pNext = NULL; 468 469 if (!pRangeLock->pWaitingTasksHead) 470 { 471 Assert(!pRangeLock->pWaitingTasksTail); 472 pRangeLock->pWaitingTasksHead = pTask; 473 pRangeLock->pWaitingTasksTail = pTask; 474 } 475 else 476 { 477 AssertPtr(pRangeLock->pWaitingTasksTail); 478 pRangeLock->pWaitingTasksTail->pNext = pTask; 479 pRangeLock->pWaitingTasksTail = pTask; 480 } 481 return true; 482 } 483 484 return false; 485 } 486 487 static int pdmacFileAioMgrNormalRangeLock(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, 488 RTFOFF offStart, size_t cbRange, 489 PPDMACTASKFILE pTask) 490 { 491 AssertMsg(!pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, offStart, cbRange, pTask), 492 ("Range is already locked offStart=%RTfoff cbRange=%u\n", 493 offStart, cbRange)); 494 495 PPDMACFILERANGELOCK pRangeLock = (PPDMACFILERANGELOCK)RTMemAllocZ(sizeof(PDMACFILERANGELOCK)); 496 if (!pRangeLock) 497 return VERR_NO_MEMORY; 498 499 /* Init the lock. */ 500 pRangeLock->Core.Key = offStart; 501 pRangeLock->Core.KeyLast = offStart + cbRange - 1; 502 pRangeLock->cRefs = 1; 503 pRangeLock->fReadLock = pTask->enmTransferType == PDMACTASKFILETRANSFER_READ; 504 505 bool fInserted = RTAvlrFileOffsetInsert(pEndpoint->AioMgr.pTreeRangesLocked, &pRangeLock->Core); 506 AssertMsg(fInserted, ("Range lock was not inserted!\n")); 507 508 /* Let the task point to its lock. */ 509 pTask->pRangeLock = pRangeLock; 510 511 return VINF_SUCCESS; 512 } 513 514 static int pdmacFileAioMgrNormalRangeLockFree(PPDMACEPFILEMGR pAioMgr, 515 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, 516 PPDMACFILERANGELOCK pRangeLock) 517 { 518 PPDMACTASKFILE pTasksWaitingHead; 519 520 AssertPtr(pRangeLock); 521 Assert(pRangeLock->cRefs == 1); 522 523 RTAvlrFileOffsetRemove(pEndpoint->AioMgr.pTreeRangesLocked, pRangeLock->Core.Key); 524 pTasksWaitingHead = pRangeLock->pWaitingTasksHead; 525 RTMemFree(pRangeLock); 526 527 return pdmacFileAioMgrNormalProcessTaskList(pTasksWaitingHead, pAioMgr, pEndpoint); 528 } 529 530 static int pdmacFileAioMgrNormalTaskPrepare(PPDMACEPFILEMGR pAioMgr, 531 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, 532 PPDMACTASKFILE pTask, PRTFILEAIOREQ phReq) 533 { 534 int rc = VINF_SUCCESS; 535 RTFILEAIOREQ hReq = NIL_RTFILEAIOREQ; 536 PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass; 537 void *pvBuf = pTask->DataSeg.pvSeg; 538 539 /* Get a request handle. */ 540 hReq = pdmacFileAioMgrNormalRequestAlloc(pAioMgr); 541 AssertMsg(hReq != NIL_RTFILEAIOREQ, ("Out of request handles\n")); 542 543 /* 544 * Check if the alignment requirements are met. 545 * Offset, transfer size and buffer address 546 * need to be on a 512 boundary. 547 */ 548 RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1); 549 size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg + (pTask->Off - offStart), 512); 550 PDMACTASKFILETRANSFER enmTransferType = pTask->enmTransferType; 551 552 AssertMsg( pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE 553 || (uint64_t)(offStart + cbToTransfer) <= pEndpoint->cbFile, 554 ("Read exceeds file size offStart=%RTfoff cbToTransfer=%d cbFile=%llu\n", 555 offStart, cbToTransfer, pEndpoint->cbFile)); 556 557 pTask->fPrefetch = false; 558 559 /* 560 * Before we start to setup the request we have to check whether there is a task 561 * already active which range intersects with ours. We have to defer execution 562 * of this task in two cases: 563 * - The pending task is a write and the current is either read or write 564 * - The pending task is a read and the current task is a write task. 565 * 566 * To check whether a range is currently "locked" we use the AVL tree where every pending task 567 * is stored by its file offset range. The current task will be added to the active task 568 * and will be executed when the active one completes. (The method below 569 * which checks whether a range is already used will add the task) 570 * 571 * This is neccessary because of the requirementto align all requests to a 512 boundary 572 * which is enforced by the host OS (Linux and Windows atm). It is possible that 573 * we have to process unaligned tasks and need to align them using bounce buffers. 574 * While the data is feteched from the file another request might arrive writing to 575 * the same range. This will result in data corruption if both are executed concurrently. 576 */ 577 bool fLocked = pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, offStart, cbToTransfer, pTask); 578 579 if (!fLocked) 580 { 581 if ( RT_UNLIKELY(cbToTransfer != pTask->DataSeg.cbSeg) 582 || RT_UNLIKELY(offStart != pTask->Off) 583 || ((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) != (RTR3UINTPTR)pvBuf)) 584 { 585 LogFlow(("Using bounce buffer for task %#p cbToTransfer=%zd cbSeg=%zd offStart=%RTfoff off=%RTfoff\n", 586 pTask, cbToTransfer, pTask->DataSeg.cbSeg, offStart, pTask->Off)); 587 588 /* Create bounce buffer. */ 589 pTask->fBounceBuffer = true; 590 591 AssertMsg(pTask->Off >= offStart, ("Overflow in calculation Off=%llu offStart=%llu\n", 592 pTask->Off, offStart)); 593 pTask->uBounceBufOffset = pTask->Off - offStart; 594 595 /** @todo: I think we need something like a RTMemAllocAligned method here. 596 * Current assumption is that the maximum alignment is 4096byte 597 * (GPT disk on Windows) 598 * so we can use RTMemPageAlloc here. 599 */ 600 pTask->pvBounceBuffer = RTMemPageAlloc(cbToTransfer); 601 if (RT_LIKELY(pTask->pvBounceBuffer)) 602 { 603 pvBuf = pTask->pvBounceBuffer; 604 605 if (pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE) 606 { 607 if ( RT_UNLIKELY(cbToTransfer != pTask->DataSeg.cbSeg) 608 || RT_UNLIKELY(offStart != pTask->Off)) 609 { 610 /* We have to fill the buffer first before we can update the data. */ 611 LogFlow(("Prefetching data for task %#p\n", pTask)); 612 pTask->fPrefetch = true; 613 enmTransferType = PDMACTASKFILETRANSFER_READ; 614 } 615 else 616 memcpy(pvBuf, pTask->DataSeg.pvSeg, pTask->DataSeg.cbSeg); 617 } 618 } 619 else 620 rc = VERR_NO_MEMORY; 621 } 622 else 623 pTask->fBounceBuffer = false; 624 625 if (RT_SUCCESS(rc)) 626 { 627 AssertMsg((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) == (RTR3UINTPTR)pvBuf, 628 ("AIO: Alignment restrictions not met! pvBuf=%p uBitmaskAlignment=%p\n", pvBuf, pEpClassFile->uBitmaskAlignment)); 629 630 if (enmTransferType == PDMACTASKFILETRANSFER_WRITE) 631 { 632 /* Grow the file if needed. */ 633 if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile)) 634 { 635 ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg); 636 RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg); 637 } 638 639 rc = RTFileAioReqPrepareWrite(hReq, pEndpoint->File, 640 offStart, pvBuf, cbToTransfer, pTask); 641 } 642 else 643 rc = RTFileAioReqPrepareRead(hReq, pEndpoint->File, 644 offStart, pvBuf, cbToTransfer, pTask); 645 AssertRC(rc); 646 647 rc = pdmacFileAioMgrNormalRangeLock(pEndpoint, offStart, cbToTransfer, pTask); 648 649 if (RT_SUCCESS(rc)) 650 *phReq = hReq; 651 else 652 { 653 /* Cleanup */ 654 if (pTask->fBounceBuffer) 655 RTMemPageFree(pTask->pvBounceBuffer); 656 } 657 } 658 } 659 else 660 { 661 LogFlow(("Task %#p was deferred because the access range is locked\n", pTask)); 662 rc = VINF_SUCCESS; 663 } 664 665 return rc; 666 } 667 401 668 static int pdmacFileAioMgrNormalProcessTaskList(PPDMACTASKFILE pTaskHead, 402 669 PPDMACEPFILEMGR pAioMgr, … … 407 674 unsigned cMaxRequests = PDMACEPFILEMGR_REQS_MAX - pAioMgr->cRequestsActive; 408 675 int rc = VINF_SUCCESS; 409 PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass;410 676 411 677 AssertMsg(pEndpoint->enmState == PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE, … … 439 705 else 440 706 { 707 Assert(!pEndpoint->pFlushReq); 441 708 pEndpoint->pFlushReq = pCurr; 442 709 } … … 447 714 { 448 715 RTFILEAIOREQ hReq = NIL_RTFILEAIOREQ; 449 void *pvBuf = pCurr->DataSeg.pvSeg; 450 451 /* Get a request handle. */ 452 if (pAioMgr->iFreeReqNext != pAioMgr->iFreeEntryNext) 716 717 rc = pdmacFileAioMgrNormalTaskPrepare(pAioMgr, pEndpoint, pCurr, &hReq); 718 AssertRC(rc); 719 720 if (hReq != NIL_RTFILEAIOREQ) 453 721 { 454 hReq = pAioMgr->pahReqsFree[pAioMgr->iFreeReqNext]; 455 pAioMgr->pahReqsFree[pAioMgr->iFreeReqNext] = NIL_RTFILEAIOREQ; 456 pAioMgr->iFreeReqNext = (pAioMgr->iFreeReqNext + 1) % pAioMgr->cReqEntries; 457 } 458 else 459 { 460 rc = RTFileAioReqCreate(&hReq); 461 AssertRC(rc); 462 } 463 464 AssertMsg(hReq != NIL_RTFILEAIOREQ, ("Out of request handles\n")); 465 466 /* Check if the alignment requirements are met. 467 * Offset, transfer size and buffer address 468 * need to be on a 512 boundary. */ 469 RTFOFF offStart = pCurr->Off & ~(RTFOFF)(512-1); 470 size_t cbToTransfer = RT_ALIGN_Z(pCurr->DataSeg.cbSeg + (pCurr->Off - offStart), 512); 471 PDMACTASKFILETRANSFER enmTransferType = pCurr->enmTransferType; 472 473 AssertMsg( pCurr->enmTransferType == PDMACTASKFILETRANSFER_WRITE 474 || (uint64_t)(offStart + cbToTransfer) <= pEndpoint->cbFile, 475 ("Read exceeds file size offStart=%RTfoff cbToTransfer=%d cbFile=%llu\n", 476 offStart, cbToTransfer, pEndpoint->cbFile)); 477 478 pCurr->fPrefetch = false; 479 480 if ( RT_UNLIKELY(cbToTransfer != pCurr->DataSeg.cbSeg) 481 || RT_UNLIKELY(offStart != pCurr->Off) 482 || ((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) != (RTR3UINTPTR)pvBuf)) 483 { 484 LogFlow(("Using bounce buffer for task %#p cbToTransfer=%zd cbSeg=%zd offStart=%RTfoff off=%RTfoff\n", 485 pCurr, cbToTransfer, pCurr->DataSeg.cbSeg, offStart, pCurr->Off)); 486 487 /* Create bounce buffer. */ 488 pCurr->fBounceBuffer = true; 489 490 AssertMsg(pCurr->Off >= offStart, ("Overflow in calculation Off=%llu offStart=%llu\n", 491 pCurr->Off, offStart)); 492 pCurr->uBounceBufOffset = pCurr->Off - offStart; 493 494 /** @todo: I think we need something like a RTMemAllocAligned method here. 495 * Current assumption is that the maximum alignment is 4096byte 496 * (GPT disk on Windows) 497 * so we can use RTMemPageAlloc here. 498 */ 499 pCurr->pvBounceBuffer = RTMemPageAlloc(cbToTransfer); 500 AssertPtr(pCurr->pvBounceBuffer); 501 pvBuf = pCurr->pvBounceBuffer; 502 503 if (pCurr->enmTransferType == PDMACTASKFILETRANSFER_WRITE) 722 apReqs[cRequests] = hReq; 723 pEndpoint->AioMgr.cReqsProcessed++; 724 cMaxRequests--; 725 cRequests++; 726 if (cRequests == RT_ELEMENTS(apReqs)) 504 727 { 505 if ( RT_UNLIKELY(cbToTransfer != pCurr->DataSeg.cbSeg) 506 || RT_UNLIKELY(offStart != pCurr->Off)) 507 { 508 /* We have to fill the buffer first before we can update the data. */ 509 LogFlow(("Prefetching data for task %#p\n", pCurr)); 510 pCurr->fPrefetch = true; 511 enmTransferType = PDMACTASKFILETRANSFER_READ; 512 } 513 else 514 memcpy(pvBuf, pCurr->DataSeg.pvSeg, pCurr->DataSeg.cbSeg); 728 rc = pdmacFileAioMgrNormalReqsEnqueue(pAioMgr, pEndpoint, apReqs, cRequests); 729 cRequests = 0; 730 AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES), 731 ("Unexpected return code\n")); 515 732 } 516 }517 else518 pCurr->fBounceBuffer = false;519 520 AssertMsg((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) == (RTR3UINTPTR)pvBuf,521 ("AIO: Alignment restrictions not met! pvBuf=%p uBitmaskAlignment=%p\n", pvBuf, pEpClassFile->uBitmaskAlignment));522 523 if (enmTransferType == PDMACTASKFILETRANSFER_WRITE)524 {525 /* Grow the file if needed. */526 if (RT_UNLIKELY((uint64_t)(pCurr->Off + pCurr->DataSeg.cbSeg) > pEndpoint->cbFile))527 {528 ASMAtomicWriteU64(&pEndpoint->cbFile, pCurr->Off + pCurr->DataSeg.cbSeg);529 RTFileSetSize(pEndpoint->File, pCurr->Off + pCurr->DataSeg.cbSeg);530 }531 532 rc = RTFileAioReqPrepareWrite(hReq, pEndpoint->File,533 offStart, pvBuf, cbToTransfer, pCurr);534 }535 else536 rc = RTFileAioReqPrepareRead(hReq, pEndpoint->File,537 offStart, pvBuf, cbToTransfer, pCurr);538 AssertRC(rc);539 540 apReqs[cRequests] = hReq;541 pEndpoint->AioMgr.cReqsProcessed++;542 cMaxRequests--;543 cRequests++;544 if (cRequests == RT_ELEMENTS(apReqs))545 {546 rc = pdmacFileAioMgrNormalReqsEnqueue(pAioMgr, pEndpoint, apReqs, cRequests);547 cRequests = 0;548 AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),549 ("Unexpected return code\n"));550 733 } 551 734 break; … … 968 1151 pEndpoint->AioMgr.cReqsProcessed++; 969 1152 1153 /* Free the lock and process pending tasks if neccessary */ 1154 pdmacFileAioMgrNormalRangeLockFree(pAioMgr, pEndpoint, pTask->pRangeLock); 1155 970 1156 /* Call completion callback */ 971 1157 pTask->pfnCompleted(pTask, pTask->pvUser); -
trunk/src/VBox/VMM/testcase/tstPDMAsyncCompletionStress.cpp
r26240 r26338 49 49 #include <iprt/thread.h> 50 50 #include <iprt/param.h> 51 #include <iprt/message.h> 51 52 52 53 #define TESTCASE "tstPDMAsyncCompletionStress" … … 179 180 180 181 if (memcmp(pbBuf, pbTestPattern, cbCompare)) 181 AssertMsgFailed(("Unexpected data for off=%RTfoff size=%u\n", pTestTask->off, pTestTask->DataSeg.cbSeg)); 182 { 183 unsigned idx = 0; 184 185 while ( (pbBuf[idx] == pbTestPattern[idx]) 186 && (idx < cbCompare)) 187 idx++; 188 189 RTMsgError("Unexpected data for off=%RTfoff size=%u\n" 190 "Expected %c got %c\n", 191 pTestTask->off + idx, pTestTask->DataSeg.cbSeg, 192 pbTestPattern[idx], pbBuf[idx]); 193 RTAssertDebugBreak(); 194 } 182 195 183 196 pbBuf += cbCompare; … … 315 328 int uRnd = RTRandU32Ex(0, 100); 316 329 317 return (uRnd < iPercentage); /* This should be enough for our purpose */330 return (uRnd <= iPercentage); /* This should be enough for our purpose */ 318 331 } 319 332
Note:
See TracChangeset
for help on using the changeset viewer.

