Changeset 59754 in vbox
- Timestamp:
- Feb 20, 2016 2:41:57 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 105624
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/list.h
r59184 r59754 161 161 } 162 162 163 164 /** 165 * Remove a node from a list, returns value. 166 * 167 * @returns pNode 168 * @param pNode The node to remove. 169 */ 170 DECLINLINE(PRTLISTNODE) RTListNodeRemoveRet(PRTLISTNODE pNode) 171 { 172 PRTLISTNODE pPrev = pNode->pPrev; 173 PRTLISTNODE pNext = pNode->pNext; 174 175 pPrev->pNext = pNext; 176 pNext->pPrev = pPrev; 177 178 /* poison */ 179 pNode->pNext = NULL; 180 pNode->pPrev = NULL; 181 182 return pNode; 183 } 184 163 185 /** 164 186 * Checks if a node is the last element in the list. … … 246 268 * Returns the first element in the list (checks for empty list). 247 269 * 248 * @retval Pointer to the first list element. 249 * @retval NULL if the list is empty. 270 * @returns Pointer to the first list element, or NULL if empty list. 250 271 * 251 272 * @param pList List to get the first element from. … … 262 283 * Returns the last element in the list (checks for empty list). 263 284 * 264 * @retval Pointer to the last list element. 265 * @retval NULL if the list is empty. 285 * @returns Pointer to the last list element, or NULL if empty list. 266 286 * 267 287 * @param pList List to get the last element from. … … 278 298 * Returns the next node in the list or NULL if the end has been reached. 279 299 * 280 * @returns The next node or NULL.300 * @returns The next node, or NULL if end of list. 281 301 * 282 302 * @param pList The list @a pCurNode is linked on. … … 294 314 * Returns the previous node in the list or NULL if the start has been reached. 295 315 * 296 * @returns The previous node or NULL.316 * @returns The previous node, or NULL if end of list. 297 317 * 298 318 * @param pList The list @a pCurNode is linked on. … … 306 326 #define RTListGetPrevCpp(pList, pCurNode, Type, Member) \ 307 327 ( (pCurNode)->Member.pPrev != (pList) ? RT_FROM_CPP_MEMBER((pCurNode)->Member.pPrev, Type, Member) : NULL ) 328 329 330 /** 331 * Removes and returns the first element in the list (checks for empty list). 332 * 333 * @returns Pointer to the first list element, or NULL if empty list. 334 * 335 * @param pList List to get the first element from. 336 * @param Type Structure the list node is a member of. 337 * @param Member The list node member. 338 */ 339 #define RTListRemoveFirst(pList, Type, Member) \ 340 (!RTListIsEmpty(pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pList)->pNext), Type, Member) : NULL) 341 /** @copydoc RTListRemoveFirst */ 342 #define RTListRemoveFirstCpp(pList, Type, Member) \ 343 (!RTListIsEmpty(pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pList)->pNext), Type, Member) : NULL) 344 345 /** 346 * Removes and returns the last element in the list (checks for empty list). 347 * 348 * @returns Pointer to the last list element, or NULL if empty list. 349 * 350 * @param pList List to get the last element from. 351 * @param Type Structure the list node is a member of. 352 * @param Member The list node member. 353 */ 354 #define RTListRemoveLast(pList, Type, Member) \ 355 (!RTListIsEmpty(pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pList)->pPrev), Type, Member) : NULL) 356 /** @copydoc RTListRemoveLast */ 357 #define RTListRemoveLastCpp(pList, Type, Member) \ 358 (!RTListIsEmpty(pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pList)->pPrev), Type, Member) : NULL) 359 360 /** 361 * Removes and returns the next node in the list or NULL if the end has been 362 * reached. 363 * 364 * @returns The next node, or NULL if end of list. 365 * 366 * @param pList The list @a pCurNode is linked on. 367 * @param pCurNode The current node, of type @a Type. 368 * @param Type Structure the list node is a member of. 369 * @param Member The list node member. 370 */ 371 #define RTListRemoveNext(pList, pCurNode, Type, Member) \ 372 ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pNext), Type, Member) : NULL ) 373 /** @copydoc RTListRemoveNext */ 374 #define RTListRemoveNextCpp(pList, pCurNode, Type, Member) \ 375 ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pNext), Type, Member) : NULL ) 376 377 /** 378 * Removes and returns the previous node in the list or NULL if the start has 379 * been reached. 380 * 381 * @returns The previous node, or NULL if end of list. 382 * 383 * @param pList The list @a pCurNode is linked on. 384 * @param pCurNode The current node, of type @a Type. 385 * @param Type Structure the list node is a member of. 386 * @param Member The list node member. 387 */ 388 #define RTListRemovePrev(pList, pCurNode, Type, Member) \ 389 ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pPrev), Type, Member) : NULL ) 390 /** @copydoc RTListRemovePrev */ 391 #define RTListRemovePrevCpp(pList, pCurNode, Type, Member) \ 392 ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_CPP_MEMBER(RTListNodeRemoveRet((pCurNode)->Member.pPrev), Type, Member) : NULL ) 393 308 394 309 395 /** -
trunk/include/iprt/mangling.h
r59747 r59754 2312 2312 # define RTVfsUtilDummyPollOne RT_MANGLER(RTVfsUtilDummyPollOne) 2313 2313 # define RTVfsUtilPumpIoStreams RT_MANGLER(RTVfsUtilPumpIoStreams) 2314 # define RTVfsCreateReadAheadForFile RT_MANGLER(RTVfsCreateReadAheadForFile) 2315 # define RTVfsCreateReadAheadForIoStream RT_MANGLER(RTVfsCreateReadAheadForIoStream) 2314 2316 # define RTZipBlockCompress RT_MANGLER(RTZipBlockCompress) 2315 2317 # define RTZipBlockDecompress RT_MANGLER(RTZipBlockDecompress) -
trunk/include/iprt/vfs.h
r59620 r59754 1010 1010 RTDECL(int) RTVfsUtilPumpIoStreams(RTVFSIOSTREAM hVfsIosSrc, RTVFSIOSTREAM hVfsIosDst, size_t cbBufHint); 1011 1011 1012 /** 1013 * Create an I/O stream instance performing simple sequential read-ahead. 1014 * 1015 * @returns IPRT status code. 1016 * @param hVfsIos The input stream to perform read ahead on. If this is 1017 * actually for a file object, the returned I/O stream 1018 * handle can also be cast to a file handle. 1019 * @param fFlags Flags reserved for future use, MBZ. 1020 * @param cBuffers How many read ahead buffers to use. Specify 0 for 1021 * default value. 1022 * @param cbBuffers The size of each read ahead buffer. Specify 0 for 1023 * default value. 1024 * @param phVfsIos Where to return the read ahead I/O stream handle. 1025 * 1026 * @remarks Careful using this on a message pipe or socket. The reads are 1027 * performed in blocked mode and it may be host and/or implementation 1028 * dependent whether they will return ready data immediate or wait 1029 * until there's a whole @a cbBuffer (or default) worth ready. 1030 * 1031 * @sa RTVfsCreateReadAheadForFile 1032 */ 1033 RTDECL(int) RTVfsCreateReadAheadForIoStream(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, uint32_t cBuffers, uint32_t cbBuffer, 1034 PRTVFSIOSTREAM phVfsIos); 1035 1036 /** 1037 * Create an I/O stream instance performing simple sequential read-ahead. 1038 * 1039 * @returns IPRT status code. 1040 * @param hVfsFile The input file to perform read ahead on. 1041 * @param fFlags Flags reserved for future use, MBZ. 1042 * @param cBuffers How many read ahead buffers to use. Specify 0 for 1043 * default value. 1044 * @param cbBuffers The size of each read ahead buffer. Specify 0 for 1045 * default value. 1046 * @param phVfsIos Where to return the read ahead I/O stream handle. 1047 * @sa RTVfsCreateReadAheadForIoStream 1048 */ 1049 RTDECL(int) RTVfsCreateReadAheadForFile(RTVFSFILE hVfsFile, uint32_t fFlags, uint32_t cBuffers, uint32_t cbBuffer, 1050 PRTVFSFILE phVfsFile); 1051 1012 1052 /** @} */ 1013 1053 -
trunk/src/VBox/Runtime/Makefile.kmk
r59751 r59754 599 599 common/vfs/vfsmemory.cpp \ 600 600 common/vfs/vfsmisc.cpp \ 601 common/vfs/vfsreadahead.cpp \ 601 602 common/vfs/vfsstdfile.cpp \ 602 603 common/vfs/vfsstdpipe.cpp \ -
trunk/src/VBox/Runtime/common/vfs/vfsreadahead.cpp
r59729 r59754 104 104 uint64_t offConsumer; 105 105 106 /** The end-of-file(/stream) offset. This is initially UINT64_MAX and later 107 * set when reading past EOF. */ 108 uint64_t offEof; 109 106 110 /** The read ahead thread. */ 107 111 RTTHREAD hThread; … … 200 204 PRTVFSREADAHEAD pThis = (PRTVFSREADAHEAD)pvThis; 201 205 202 Assert(pSgBuf->cSegs == 1); 206 Assert(pSgBuf->cSegs == 1); /* Caller deals with multiple SGs. */ 203 207 Assert(off < 0); 204 208 NOREF(fBlocking); … … 209 213 * section, just in case a buffer got inserted while we were waiting for it. 210 214 */ 211 int rc = VINF_SUCCESS; 212 size_t cbTotalRead = 0; 213 bool fPokeReader = false; 214 bool fOwnsIoCritSect = false; 215 int rc = VINF_SUCCESS; 216 uint8_t *pbDst = (uint8_t *)pSgBuf->paSegs[0].pvSeg; 217 size_t cbDst = pSgBuf->paSegs[0].cbSeg; 218 size_t cbTotalRead = 0; 219 bool fPokeReader = false; 220 bool fOwnsIoCritSect = false; 215 221 RTCritSectEnter(&pThis->BufferCritSect); 216 222 for (;;) 217 223 { 218 224 /* 219 * Try satisfy the read from the buffer .225 * Try satisfy the read from the buffers. 220 226 */ 221 227 uint64_t offCur = pThis->offConsumer; … … 223 229 { 224 230 offCur = (uint64_t)off; 231 if (pThis->offConsumer != offCur) 232 fPokeReader = true; /* If the current position changed, poke it in case it stopped at EOF. */ 225 233 pThis->offConsumer = offCur; 226 234 } 227 235 228 PRTVFSREADAHEADBUFDESC p CurBufDesc;229 RTListForEach (&pThis->ConsumerList, pCurBufDesc, RTVFSREADAHEADBUFDESC, ListEntry)236 PRTVFSREADAHEADBUFDESC pBufDesc, pNextBufDesc; 237 RTListForEachSafe(&pThis->ConsumerList, pBufDesc, pNextBufDesc, RTVFSREADAHEADBUFDESC, ListEntry) 230 238 { 231 if (pThis->offConsumer) 239 /* The buffers are sorted and reads must start in a buffer if 240 anything should be taken from the buffer (at least for now). */ 241 if (offCur < pBufDesc->off) 242 break; 243 244 /* Anything we can read from this buffer? */ 245 uint64_t offCurBuf = offCur - pBufDesc->off; 246 if (offCurBuf < pBufDesc->cbFilled) 232 247 { 248 size_t const cbFromCurBuf = RT_MIN(pBufDesc->cbFilled - offCurBuf, cbDst); 249 memcpy(pbDst, pBufDesc->pbBuffer + offCurBuf, cbFromCurBuf); 250 pbDst += cbFromCurBuf; 251 cbDst -= cbFromCurBuf; 252 cbTotalRead += cbFromCurBuf; 253 offCur += cbFromCurBuf; 233 254 } 255 256 /* Discard buffers we've read past. */ 257 if (pBufDesc->off + pBufDesc->cbFilled <= offCur) 258 { 259 RTListNodeRemove(&pBufDesc->ListEntry); 260 RTListAppend(&pThis->FreeList, &pBufDesc->ListEntry); 261 fPokeReader = true; /* Poke it as there are now more buffers available. */ 262 } 263 264 /* Stop if we're done. */ 265 if (!cbDst) 266 break; 234 267 } 235 /** @todo EOF handling! */ 236 if (pSgBuf->cbSegLeft == 0) 268 269 pThis->offConsumer = offCur; 270 if (off != -1) 271 off = offCur; 272 273 if (!cbDst) 237 274 break; 275 276 /* 277 * Check if we've reached the end of the file/stream. 278 */ 279 if (offCur >= pThis->offEof) 280 { 281 rc = pcbRead ? VINF_EOF : VERR_EOF; 282 break; 283 } 284 238 285 239 286 /* … … 250 297 } 251 298 299 252 300 /* 253 301 * Do a direct read of the remaining data. 254 302 */ 255 //size_t cbDirectRead; 256 257 303 if (off == -1) 304 { 305 RTFOFF offActual = RTVfsIoStrmTell(pThis->hIos); 306 if (offActual >= 0 && (uint64_t)offActual != offCur) 307 off = offCur; 308 } 309 RTSGSEG TmpSeg = { pbDst, cbDst }; 310 RTSGBUF TmpSgBuf; 311 RTSgBufInit(&TmpSgBuf, &TmpSeg, 1); 312 size_t cbThisRead = cbDst; 313 rc = RTVfsIoStrmSgRead(pThis->hIos, off, pSgBuf, fBlocking, pcbRead ? &cbThisRead : NULL); 314 if (RT_SUCCESS(rc)) 315 { 316 cbTotalRead = cbThisRead; 317 offCur += cbThisRead; 318 pThis->offConsumer = offCur; 319 if (rc != VINF_EOF) 320 fPokeReader = true; 321 else 322 pThis->offEof = offCur; 323 } 324 /* else if (rc == VERR_EOF): hard to say where exactly the current position 325 is here as cannot have had a non-NULL pcbRead. Set offEof later. */ 326 break; 258 327 } 259 328 RTCritSectLeave(&pThis->BufferCritSect); 260 329 if (fOwnsIoCritSect) 261 330 RTCritSectLeave(&pThis->IoCritSect); 262 if (fPokeReader )331 if (fPokeReader && rc != VINF_EOF && rc != VERR_EOF) 263 332 RTThreadUserSignal(pThis->hThread); 264 333 … … 487 556 Assert(pThis); 488 557 489 while ( pThis->fTerminateThread)558 while (!pThis->fTerminateThread) 490 559 { 491 560 int rc; 492 561 493 /** @todo EOF handling. */494 562 /* 495 563 * Is there a buffer handy for reading ahead. … … 498 566 RTCritSectEnter(&pThis->BufferCritSect); 499 567 if (!pThis->fTerminateThread) 500 pBufDesc = RTList GetFirst(&pThis->FreeList, RTVFSREADAHEADBUFDESC, ListEntry);568 pBufDesc = RTListRemoveFirst(&pThis->FreeList, RTVFSREADAHEADBUFDESC, ListEntry); 501 569 RTCritSectLeave(&pThis->BufferCritSect); 502 570 … … 516 584 if (RT_SUCCESS(rc)) 517 585 { 586 if (rc == VINF_EOF) 587 pThis->offEof = pBufDesc->off + cbRead; 518 588 pBufDesc->cbFilled = (uint32_t)cbRead; 519 589 … … 534 604 RTListPrepend(&pThis->ConsumerList, &pBufDesc->ListEntry); 535 605 else 606 { 607 Assert(pAfter->off <= pBufDesc->off); 536 608 RTListNodeInsertAfter(&pAfter->ListEntry, &pBufDesc->ListEntry); 609 } 537 610 } 538 611 RTCritSectLeave(&pThis->BufferCritSect); 539 612 pBufDesc = NULL; 613 614 #ifdef RT_STRICT 615 /* Verify the list ordering. */ 616 unsigned cAsserted = 0; 617 uint64_t offAssert = 0; 618 PRTVFSREADAHEADBUFDESC pAssertCur; 619 RTListForEach(&pThis->ConsumerList, pAssertCur, RTVFSREADAHEADBUFDESC, ListEntry) 620 { 621 Assert(offAssert <= pAssertCur->off); 622 offAssert = pAssertCur->off; 623 Assert(cAsserted < pThis->cBuffers); 624 cAsserted++; 625 } 626 #endif 540 627 } 628 else 629 Assert(rc != VERR_EOF); 541 630 } 542 631 RTCritSectLeave(&pThis->IoCritSect); 543 632 544 633 /* 545 * If we succeeded, loop without delay to start processing the next buffer. 634 * If we succeeded and we didn't yet reach the end of the stream, 635 * loop without delay to start processing the next buffer. 546 636 */ 547 if (RT_LIKELY(!pBufDesc ))637 if (RT_LIKELY(!pBufDesc && rc != VINF_EOF)) 548 638 continue; 549 639 550 /* On failure or termination, put the buffer back in the free list and wait. */ 551 RTCritSectEnter(&pThis->BufferCritSect); 552 RTListPrepend(&pThis->FreeList, &pBufDesc->ListEntry); 553 RTCritSectLeave(&pThis->BufferCritSect); 640 /* Put any unused buffer back in the free list (termination/failure, not EOF). */ 641 if (pBufDesc) 642 { 643 RTCritSectEnter(&pThis->BufferCritSect); 644 RTListPrepend(&pThis->FreeList, &pBufDesc->ListEntry); 645 RTCritSectLeave(&pThis->BufferCritSect); 646 } 554 647 if (pThis->fTerminateThread) 555 648 break; … … 609 702 pThis->cBuffers = cBuffers; 610 703 pThis->cbBuffer = cbBuffer; 704 pThis->offEof = UINT64_MAX; 611 705 pThis->offConsumer = RTVfsIoStrmTell(hVfsIosSrc); 612 706 if ((RTFOFF)pThis->offConsumer >= 0)
Note:
See TracChangeset
for help on using the changeset viewer.