Changeset 24278 in vbox
- Timestamp:
- Nov 2, 2009 8:26:07 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 54251
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp
r24059 r24278 42 42 #include <iprt/string.h> 43 43 #include <iprt/thread.h> 44 #include <iprt/path.h> 44 45 45 46 #include "PDMAsyncCompletionFileInternal.h" … … 693 694 } 694 695 696 #ifdef VBOX_WITH_STATISTICS 697 if (RT_SUCCESS(rc)) 698 { 699 STAMR3RegisterF(pEpClassFile->Core.pVM, &pEpFile->StatRead, 700 STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, 701 STAMUNIT_TICKS_PER_CALL, "Time taken to read from the endpoint", 702 "/PDM/AsyncCompletion/File/%s/Read", RTPathFilename(pEpFile->Core.pszUri)); 703 704 STAMR3RegisterF(pEpClassFile->Core.pVM, &pEpFile->StatWrite, 705 STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, 706 STAMUNIT_TICKS_PER_CALL, "Time taken to write to the endpoint", 707 "/PDM/AsyncCompletion/File/%s/Write", RTPathFilename(pEpFile->Core.pszUri)); 708 } 709 #endif 710 695 711 return rc; 696 712 } … … 728 744 RTFileClose(pEpFile->File); 729 745 746 #ifdef VBOX_WITH_STATISTICS 747 STAMR3Deregister(pEpClassFile->Core.pVM, &pEpFile->StatRead); 748 STAMR3Deregister(pEpClassFile->Core.pVM, &pEpFile->StatWrite); 749 #endif 750 730 751 return VINF_SUCCESS; 731 752 } … … 736 757 size_t cbRead) 737 758 { 759 int rc = VINF_SUCCESS; 738 760 PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint; 739 761 762 STAM_PROFILE_ADV_START(&pEpFile->StatRead, Read); 763 740 764 if (pEpFile->fCaching) 741 r eturnpdmacFileEpCacheRead(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask,742 765 rc = pdmacFileEpCacheRead(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask, 766 off, paSegments, cSegments, cbRead); 743 767 else 744 return pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbRead, 745 PDMACTASKFILETRANSFER_READ); 768 rc = pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbRead, 769 PDMACTASKFILETRANSFER_READ); 770 771 STAM_PROFILE_ADV_STOP(&pEpFile->StatRead, Read); 772 773 return rc; 746 774 } 747 775 … … 751 779 size_t cbWrite) 752 780 { 781 int rc = VINF_SUCCESS; 753 782 PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint; 754 783 … … 756 785 return VERR_NOT_SUPPORTED; 757 786 787 STAM_PROFILE_ADV_START(&pEpFile->StatWrite, Write); 788 758 789 if (pEpFile->fCaching) 759 r eturnpdmacFileEpCacheWrite(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask,760 790 rc = pdmacFileEpCacheWrite(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask, 791 off, paSegments, cSegments, cbWrite); 761 792 else 762 return pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbWrite, 763 PDMACTASKFILETRANSFER_WRITE); 793 rc = pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbWrite, 794 PDMACTASKFILETRANSFER_WRITE); 795 796 STAM_PROFILE_ADV_STOP(&pEpFile->StatWrite, Write); 797 798 return rc; 764 799 } 765 800 -
trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp
r24202 r24278 47 47 #include <iprt/types.h> 48 48 #include <iprt/mem.h> 49 #include <iprt/path.h> 49 50 #include <VBox/log.h> 50 51 #include <VBox/stam.h> … … 714 715 } 715 716 717 #ifdef VBOX_WITH_STATISTICS 718 if (RT_SUCCESS(rc)) 719 { 720 STAMR3RegisterF(pClassFile->Core.pVM, &pEndpointCache->StatWriteDeferred, 721 STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, 722 STAMUNIT_COUNT, "Number of deferred writes", 723 "/PDM/AsyncCompletion/File/%s/Cache/DeferredWrites", RTPathFilename(pEndpoint->Core.pszUri)); 724 } 725 #endif 726 716 727 return rc; 717 728 } … … 768 779 769 780 RTSemRWDestroy(pEndpointCache->SemRWEntries); 781 782 #ifdef VBOX_WITH_STATISTICS 783 PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass; 784 785 STAMR3Deregister(pEpClassFile->Core.pVM, &pEndpointCache->StatWriteDeferred); 786 #endif 770 787 } 771 788 … … 884 901 pEntry->pWaitingTail = pSeg; 885 902 } 903 } 904 905 /** 906 * Checks that a set of flags is set/clear acquiring the R/W semaphore 907 * in exclusive mode. 908 * 909 * @returns true if the flag in fSet is set and the one in fClear is clear. 910 * false othwerise. 911 * The R/W semaphore is only held if true is returned. 912 * 913 * @param pEndpointCache The endpoint cache instance data. 914 * @param pEntry The entry to check the flags for. 915 * @param fSet The flag which is tested to be set. 916 * @param fClear The flag which is tested to be clear. 917 */ 918 DECLINLINE(bool) pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(PPDMACFILEENDPOINTCACHE pEndpointCache, 919 PPDMACFILECACHEENTRY pEntry, 920 uint32_t fSet, uint32_t fClear) 921 { 922 bool fPassed = ((pEntry->fFlags & fSet) && !(pEntry->fFlags & fClear)); 923 924 if (fPassed) 925 { 926 /* Acquire the lock and check again becuase the completion callback might have raced us. */ 927 RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT); 928 929 fPassed = ((pEntry->fFlags & fSet) && !(pEntry->fFlags & fClear)); 930 931 /* Drop the lock if we didn't passed the test. */ 932 if (!fPassed) 933 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 934 } 935 936 return fPassed; 886 937 } 887 938 … … 979 1030 LogFlow(("Fetching data for ghost entry %#p from file\n", pEntry)); 980 1031 981 if ( (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS) 982 && !(pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY)) 1032 if (pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry, 1033 PDMACFILECACHE_ENTRY_IO_IN_PROGRESS, 1034 PDMACFILECACHE_ENTRY_IS_DIRTY)) 983 1035 { 984 RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT); 985 /* Check again. The completion callback might have raced us. */ 986 987 if ( (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS) 988 && !(pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY)) 1036 /* Entry didn't completed yet. Append to the list */ 1037 while (cbToRead) 989 1038 { 990 /* Entry didn't completed yet. Append to the list */ 991 while (cbToRead) 992 { 993 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG)); 994 995 pSeg->pTask = pTask; 996 pSeg->uBufOffset = OffDiff; 997 pSeg->cbTransfer = RT_MIN(cbToRead, cbSegLeft); 998 pSeg->pvBuf = pbSegBuf; 999 pSeg->fWrite = false; 1000 1001 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer); 1002 1003 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg); 1004 1005 off += pSeg->cbTransfer; 1006 cbToRead -= pSeg->cbTransfer; 1007 OffDiff += pSeg->cbTransfer; 1008 } 1009 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1039 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG)); 1040 1041 pSeg->pTask = pTask; 1042 pSeg->uBufOffset = OffDiff; 1043 pSeg->cbTransfer = RT_MIN(cbToRead, cbSegLeft); 1044 pSeg->pvBuf = pbSegBuf; 1045 pSeg->fWrite = false; 1046 1047 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer); 1048 1049 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg); 1050 1051 off += pSeg->cbTransfer; 1052 cbToRead -= pSeg->cbTransfer; 1053 OffDiff += pSeg->cbTransfer; 1010 1054 } 1011 else 1012 { 1013 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1014 1015 /* Read as much as we can from the entry. */ 1016 while (cbToRead) 1017 { 1018 size_t cbCopy = RT_MIN(cbSegLeft, cbToRead); 1019 1020 memcpy(pbSegBuf, pEntry->pbData + OffDiff, cbCopy); 1021 1022 ADVANCE_SEGMENT_BUFFER(cbCopy); 1023 1024 cbToRead -= cbCopy; 1025 off += cbCopy; 1026 OffDiff += cbCopy; 1027 ASMAtomicSubS32(&pTask->cbTransferLeft, cbCopy); 1028 } 1029 } 1055 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1030 1056 } 1031 1057 else … … 1277 1303 || (pEntry->pList == &pCache->LruFrequentlyUsed)) 1278 1304 { 1279 if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY) 1305 1306 /* If the entry is dirty it must be also in progress now and we have to defer updating it again. */ 1307 if(pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry, 1308 PDMACFILECACHE_ENTRY_IS_DIRTY, 1309 0)) 1280 1310 { 1281 RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT); 1282 /* Check again. The completion callback might have raced us. */ 1283 1284 if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY) 1311 AssertMsg(pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS, 1312 ("Entry is dirty but not in progress\n")); 1313 1314 /* The data isn't written to the file yet */ 1315 while (cbToWrite) 1285 1316 { 1286 AssertMsg(pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS, 1287 ("Entry is dirty but not in progress\n")); 1288 1289 /* The data isn't written to the file yet */ 1290 while (cbToWrite) 1291 { 1292 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG)); 1293 1294 pSeg->pTask = pTask; 1295 pSeg->uBufOffset = OffDiff; 1296 pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft); 1297 pSeg->pvBuf = pbSegBuf; 1298 pSeg->fWrite = true; 1299 1300 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer); 1301 1302 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg); 1303 1304 off += pSeg->cbTransfer; 1305 OffDiff += pSeg->cbTransfer; 1306 cbToWrite -= pSeg->cbTransfer; 1307 } 1308 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1317 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG)); 1318 1319 pSeg->pTask = pTask; 1320 pSeg->uBufOffset = OffDiff; 1321 pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft); 1322 pSeg->pvBuf = pbSegBuf; 1323 pSeg->fWrite = true; 1324 1325 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer); 1326 1327 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg); 1328 1329 off += pSeg->cbTransfer; 1330 OffDiff += pSeg->cbTransfer; 1331 cbToWrite -= pSeg->cbTransfer; 1309 1332 } 1310 else 1311 { 1312 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1313 1314 AssertMsg(!(pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS), 1315 ("Entry is not dirty but in progress\n")); 1316 1317 /* Write as much as we can into the entry and update the file. */ 1318 while (cbToWrite) 1319 { 1320 size_t cbCopy = RT_MIN(cbSegLeft, cbToWrite); 1321 1322 memcpy(pEntry->pbData + OffDiff, pbSegBuf, cbCopy); 1323 1324 ADVANCE_SEGMENT_BUFFER(cbCopy); 1325 1326 cbToWrite-= cbCopy; 1327 off += cbCopy; 1328 OffDiff += cbCopy; 1329 ASMAtomicSubS32(&pTask->cbTransferLeft, cbCopy); 1330 } 1331 1332 pEntry->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY; 1333 pdmacFileCacheWriteToEndpoint(pEntry); 1334 } 1333 STAM_COUNTER_INC(&pEndpointCache->StatWriteDeferred); 1334 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1335 1335 } 1336 1336 else … … 1340 1340 * We have to defer processing in that case. 1341 1341 */ 1342 if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS) 1342 if(pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry, 1343 PDMACFILECACHE_ENTRY_IO_IN_PROGRESS, 1344 0)) 1343 1345 { 1344 RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT); 1345 1346 /* Check again. The completion callback might have raced us. */ 1347 if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS) 1346 while (cbToWrite) 1348 1347 { 1349 1350 while (cbToWrite) 1351 { 1352 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG)); 1353 1354 pSeg->pTask = pTask; 1355 pSeg->uBufOffset = OffDiff; 1356 pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft); 1357 pSeg->pvBuf = pbSegBuf; 1358 pSeg->fWrite = true; 1359 1360 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer); 1361 1362 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg); 1363 1364 off += pSeg->cbTransfer; 1365 OffDiff += pSeg->cbTransfer; 1366 cbToWrite -= pSeg->cbTransfer; 1367 } 1368 1369 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1348 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG)); 1349 1350 pSeg->pTask = pTask; 1351 pSeg->uBufOffset = OffDiff; 1352 pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft); 1353 pSeg->pvBuf = pbSegBuf; 1354 pSeg->fWrite = true; 1355 1356 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer); 1357 1358 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg); 1359 1360 off += pSeg->cbTransfer; 1361 OffDiff += pSeg->cbTransfer; 1362 cbToWrite -= pSeg->cbTransfer; 1370 1363 } 1371 else 1372 { 1373 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1374 1375 /* Write as much as we can into the entry and update the file. */ 1376 while (cbToWrite) 1377 { 1378 size_t cbCopy = RT_MIN(cbSegLeft, cbToWrite); 1379 1380 memcpy(pEntry->pbData + OffDiff, pbSegBuf, cbCopy); 1381 1382 ADVANCE_SEGMENT_BUFFER(cbCopy); 1383 1384 cbToWrite-= cbCopy; 1385 off += cbCopy; 1386 OffDiff += cbCopy; 1387 ASMAtomicSubS32(&pTask->cbTransferLeft, cbCopy); 1388 } 1389 1390 pEntry->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY; 1391 pdmacFileCacheWriteToEndpoint(pEntry); 1392 } 1364 STAM_COUNTER_INC(&pEndpointCache->StatWriteDeferred); 1365 RTSemRWReleaseWrite(pEndpointCache->SemRWEntries); 1393 1366 } 1394 1367 else … … 1455 1428 } 1456 1429 1430 STAM_COUNTER_INC(&pEndpointCache->StatWriteDeferred); 1457 1431 pdmacFileCacheReadFromEndpoint(pEntry); 1458 1432 } … … 1526 1500 } 1527 1501 1502 pEntryNew->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY; 1528 1503 pdmacFileCacheWriteToEndpoint(pEntryNew); 1529 1504 pdmacFileEpCacheEntryRelease(pEntryNew); /* it is protected by the I/O in progress flag now. */ -
trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h
r23975 r24278 308 308 /** Pointer to the gobal cache data */ 309 309 PPDMACFILECACHEGLOBAL pCache; 310 311 #ifdef VBOX_WITH_STATISTICS 312 /** Number of times a write was deferred because the cache entry was still in progress */ 313 STAMCOUNTER StatWriteDeferred; 314 #endif 310 315 } PDMACFILEENDPOINTCACHE, *PPDMACFILEENDPOINTCACHE; 311 316 … … 423 428 /** Blocking event type */ 424 429 PDMACEPFILEBLOCKINGEVENT enmBlockingEvent; 430 431 #ifdef VBOX_WITH_STATISTICS 432 /** Time spend in a read. */ 433 STAMPROFILEADV StatRead; 434 /** Time spend in a write. */ 435 STAMPROFILEADV StatWrite; 436 #endif 437 425 438 /** Additional data needed for the event types. */ 426 439 union
Note:
See TracChangeset
for help on using the changeset viewer.