Changeset 19370 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- May 5, 2009 12:20:09 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 46871
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/fileaio-posix.cpp
r19348 r19370 47 47 #include <aio.h> 48 48 #include <errno.h> 49 50 #define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64 49 #include <time.h> 50 51 /* 52 * Linux does not define this value. 53 * Just define it with really big 54 * value. 55 */ 56 #ifndef AIO_LISTIO_MAX 57 # define AIO_LISTIO_MAX UINT32_MAX 58 #endif 51 59 52 60 /******************************************************************************* … … 417 425 } 418 426 419 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ phReqs, size_t cReqs, size_t *pcReqs) 420 { 427 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs) 428 { 429 int rc = VINF_SUCCESS; 421 430 PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; 422 431 … … 424 433 AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE); 425 434 AssertReturn(cReqs != 0, VERR_INVALID_POINTER); 426 AssertPtrReturn(p hReqs, VERR_INVALID_PARAMETER);435 AssertPtrReturn(pahReqs, VERR_INVALID_PARAMETER); 427 436 428 437 /* Check that we don't exceed the limit */ … … 431 440 432 441 PRTFILEAIOREQINTERNAL pHead = NULL; 433 for (size_t i = 0; i < cReqs; i++) 434 { 435 PRTFILEAIOREQINTERNAL pReqInt = phReqs[i]; 436 437 pReqInt->pCtxInt = pCtxInt; 438 /* Link them together. */ 439 pReqInt->pNext = pHead; 440 pHead = pReqInt; 441 } 442 443 int rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)phReqs, cReqs, NULL); 444 if (RT_UNLIKELY(rcPosix < 0)) 445 return RTErrConvertFromErrno(errno); 446 447 ASMAtomicAddS32(&pCtxInt->cRequests, cReqs); 448 *pcReqs = cReqs; 449 450 /* 451 * Forward them to the thread waiting for requests. 452 * We search for a free slot first and if we don't find one 453 * we will grab the first one and append our list to the existing entries. 454 */ 455 unsigned iSlot = 0; 456 while ( (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead)) 457 && !ASMAtomicCmpXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[iSlot], pHead, NULL)) 458 iSlot++; 459 460 if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead)) 461 { 462 /* Nothing found. */ 463 PRTFILEAIOREQINTERNAL pOldHead = (PRTFILEAIOREQINTERNAL)ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], 464 NULL); 465 466 /* Find the end of the current head and link the old list to the current. */ 467 PRTFILEAIOREQINTERNAL pTail = pHead; 468 while (pTail->pNext) 469 pTail = pTail->pNext; 470 471 pTail->pNext = pOldHead; 472 473 ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], pHead); 474 } 475 476 /* Set the internal wakeup flag and wakeup the thread if possible. */ 477 bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true); 478 if (!fWokenUp) 479 rtFileAioCtxWakeup(pCtxInt); 480 481 return VINF_SUCCESS; 442 443 do 444 { 445 int rcPosix = 0; 446 size_t cReqsSubmit = 0; 447 size_t i = 0; 448 PRTFILEAIOREQINTERNAL pReqInt; 449 450 while ( (i < cReqs) 451 && (i < AIO_LISTIO_MAX)) 452 { 453 pReqInt = pahReqs[i]; 454 RTFILEAIOREQ_VALID_RETURN(pReqInt); 455 456 pReqInt->pCtxInt = pCtxInt; 457 458 /* Link them together. */ 459 pReqInt->pNext = pHead; 460 pHead = pReqInt; 461 462 if (pReqInt->fFlush) 463 break; 464 465 cReqsSubmit++; 466 i++; 467 } 468 469 if (cReqsSubmit) 470 { 471 rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); 472 if (RT_UNLIKELY(rcPosix < 0)) 473 { 474 rc = RTErrConvertFromErrno(errno); 475 break; 476 } 477 478 ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); 479 cReqs -= cReqsSubmit; 480 pahReqs += cReqsSubmit; 481 *pcReqs += cReqsSubmit; 482 } 483 484 /* Check if we have a flush request now. */ 485 if (cReqs) 486 { 487 pReqInt = pahReqs[0]; 488 RTFILEAIOREQ_VALID_RETURN(pReqInt); 489 490 if (pReqInt->fFlush) 491 { 492 /* 493 * lio_listio does not work with flush requests so 494 * we have to use aio_fsync directly. 495 */ 496 rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB); 497 if (RT_UNLIKELY(rcPosix < 0)) 498 { 499 rc = RTErrConvertFromErrno(errno); 500 break; 501 } 502 503 ASMAtomicIncS32(&pCtxInt->cRequests); 504 cReqs--; 505 pahReqs++; 506 *pcReqs++; 507 } 508 } 509 } while (cReqs); 510 511 if (pHead) 512 { 513 /* 514 * Forward successfully submitted requests to the thread waiting for requests. 515 * We search for a free slot first and if we don't find one 516 * we will grab the first one and append our list to the existing entries. 517 */ 518 unsigned iSlot = 0; 519 while ( (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead)) 520 && !ASMAtomicCmpXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[iSlot], pHead, NULL)) 521 iSlot++; 522 523 if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead)) 524 { 525 /* Nothing found. */ 526 PRTFILEAIOREQINTERNAL pOldHead = (PRTFILEAIOREQINTERNAL)ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], 527 NULL); 528 529 /* Find the end of the current head and link the old list to the current. */ 530 PRTFILEAIOREQINTERNAL pTail = pHead; 531 while (pTail->pNext) 532 pTail = pTail->pNext; 533 534 pTail->pNext = pOldHead; 535 536 ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], pHead); 537 } 538 539 /* Set the internal wakeup flag and wakeup the thread if possible. */ 540 bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true); 541 if (!fWokenUp) 542 rtFileAioCtxWakeup(pCtxInt); 543 } 544 545 return rc; 482 546 } 483 547
Note:
See TracChangeset
for help on using the changeset viewer.