diff options
Diffstat (limited to 'src/VBox/Runtime/r3/posix/fileaio-posix.cpp')
-rw-r--r-- | src/VBox/Runtime/r3/posix/fileaio-posix.cpp | 97 |
1 files changed, 75 insertions, 22 deletions
diff --git a/src/VBox/Runtime/r3/posix/fileaio-posix.cpp b/src/VBox/Runtime/r3/posix/fileaio-posix.cpp index 7f5ac6944..7e67876ee 100644 --- a/src/VBox/Runtime/r3/posix/fileaio-posix.cpp +++ b/src/VBox/Runtime/r3/posix/fileaio-posix.cpp @@ -1,4 +1,4 @@ -/* $Id: fileaio-posix.cpp 29129 2010-05-06 10:40:30Z vboxsync $ */ +/* $Id: fileaio-posix.cpp 29477 2010-05-14 14:59:29Z vboxsync $ */ /** @file * IPRT - File async I/O, native implementation for POSIX compliant host platforms. */ @@ -68,6 +68,11 @@ /** Invalid entry in the waiting array. */ #define RTFILEAIOCTX_WAIT_ENTRY_INVALID (~0U) +/** No-op replacement for rtFileAioCtxDump for non debug builds */ +#ifndef LOG_ENABLED +# define rtFileAioCtxDump(pCtxInt) do {} while (0) +#endif + /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ @@ -198,6 +203,7 @@ static int rtFileAioCtxProcessEvents(PRTFILEAIOCTXINTERNAL pCtxInt) while ( (pCtxInt->iFirstFree < pCtxInt->cReqsWaitMax) && pReqHead) { + RTFIELAIOREQ_ASSERT_STATE(pReqHead, SUBMITTED); pCtxInt->apReqs[pCtxInt->iFirstFree] = pReqHead; pReqHead->iWaitingList = pCtxInt->iFirstFree; pReqHead = pReqHead->pNext; @@ -214,6 +220,7 @@ static int rtFileAioCtxProcessEvents(PRTFILEAIOCTXINTERNAL pCtxInt) /* Append the rest to the wait list. */ if (pReqHead) { + RTFIELAIOREQ_ASSERT_STATE(pReqHead, SUBMITTED); if (!pCtxInt->pReqsWaitHead) { Assert(!pCtxInt->pReqsWaitTail); @@ -230,7 +237,10 @@ static int rtFileAioCtxProcessEvents(PRTFILEAIOCTXINTERNAL pCtxInt) /* Update tail. */ while (pReqHead->pNext) + { + RTFIELAIOREQ_ASSERT_STATE(pReqHead->pNext, SUBMITTED); pReqHead = pReqHead->pNext; + } pCtxInt->pReqsWaitTail = pReqHead; pCtxInt->pReqsWaitTail->pNext = NULL; @@ -578,6 +588,30 @@ RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile) return VINF_SUCCESS; } +#ifdef LOG_ENABLED +/** + * Dumps the state of a async I/O context. + */ +static void rtFileAioCtxDump(PRTFILEAIOCTXINTERNAL pCtxInt) +{ + LogFlow(("cRequests=%d\n", pCtxInt->cRequests)); + LogFlow(("cMaxRequests=%u\n", pCtxInt->cMaxRequests)); + LogFlow(("hThreadWait=%#p\n", pCtxInt->hThreadWait)); + LogFlow(("fWokenUp=%RTbool\n", pCtxInt->fWokenUp)); + LogFlow(("fWaiting=%RTbool\n", pCtxInt->fWaiting)); + LogFlow(("fWokenUpInternal=%RTbool\n", pCtxInt->fWokenUpInternal)); + for (unsigned i = 0; i < RT_ELEMENTS(pCtxInt->apReqsNewHead); i++) + LogFlow(("apReqsNewHead[%u]=%#p\n", i, pCtxInt->apReqsNewHead[i])); + LogFlow(("pReqToCancel=%#p\n", pCtxInt->pReqToCancel)); + LogFlow(("pReqsWaitHead=%#p\n", pCtxInt->pReqsWaitHead)); + LogFlow(("pReqsWaitTail=%#p\n", pCtxInt->pReqsWaitTail)); + LogFlow(("cReqsWaitMax=%u\n", pCtxInt->cReqsWaitMax)); + LogFlow(("iFirstFree=%u\n", pCtxInt->iFirstFree)); + for (unsigned i = 0; i < pCtxInt->cReqsWaitMax; i++) + LogFlow(("apReqs[%u]=%#p\n", i, pCtxInt->apReqs[i])); +} +#endif + RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) { int rc = VINF_SUCCESS; @@ -588,6 +622,8 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size AssertReturn(cReqs != 0, VERR_INVALID_POINTER); AssertPtrReturn(pahReqs, VERR_INVALID_PARAMETER); + rtFileAioCtxDump(pCtxInt); + /* Check that we don't exceed the limit */ if (ASMAtomicUoReadS32(&pCtxInt->cRequests) + cReqs > pCtxInt->cMaxRequests) return VERR_FILE_AIO_LIMIT_EXCEEDED; @@ -631,6 +667,9 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size pReqInt->pCtxInt = pCtxInt; + if (pReqInt->fFlush) + break; + /* Link them together. */ pReqInt->pNext = pHead; if (pHead) @@ -639,9 +678,6 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size pHead = pReqInt; RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); - if (pReqInt->fFlush) - break; - cReqsSubmit++; i++; } @@ -712,12 +748,12 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size } } ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted); - AssertMsg(pCtxInt->cRequests > 0, ("Adding requests resulted in overflow\n")); + AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n")); break; } ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); - AssertMsg(pCtxInt->cRequests > 0, ("Adding requests resulted in overflow\n")); + AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n")); cReqs -= cReqsSubmit; pahReqs += cReqsSubmit; } @@ -731,7 +767,6 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size if (cReqs && RT_SUCCESS_NP(rc)) { pReqInt = pahReqs[0]; - RTFILEAIOREQ_VALID_RETURN(pReqInt); if (pReqInt->fFlush) { @@ -742,26 +777,31 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB); if (RT_UNLIKELY(rcPosix < 0)) { - rc = RTErrConvertFromErrno(errno); - RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); - pReqInt->Rc = rc; - pReqInt->cbTransfered = 0; - - /* Unlink from the list. */ - PRTFILEAIOREQINTERNAL pNext, pPrev; - pNext = pReqInt->pNext; - pPrev = pReqInt->pPrev; - if (pNext) - pNext->pPrev = pPrev; - if (pPrev) - pPrev->pNext = pNext; + if (errno == EAGAIN) + { + rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; + RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); + } else - pHead = pNext; + { + rc = RTErrConvertFromErrno(errno); + RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); + pReqInt->Rc = rc; + } + pReqInt->cbTransfered = 0; break; } + /* Link them together. */ + pReqInt->pNext = pHead; + if (pHead) + pHead->pPrev = pReqInt; + pReqInt->pPrev = NULL; + pHead = pReqInt; + RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); + ASMAtomicIncS32(&pCtxInt->cRequests); - AssertMsg(pCtxInt->cRequests > 0, ("Adding requests resulted in overflow\n")); + AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n")); cReqs--; pahReqs++; } @@ -803,6 +843,8 @@ RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size rtFileAioCtxWakeup(pCtxInt); } + rtFileAioCtxDump(pCtxInt); + return rc; } @@ -817,6 +859,9 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL struct timespec *pTimeout = NULL; uint64_t StartNanoTS = 0; + LogFlowFunc(("hAioCtx=%#p cMinReqs=%zu cMillies=%u pahReqs=%#p cReqs=%zu pcbReqs=%#p\n", + hAioCtx, cMinReqs, cMillies, pahReqs, cReqs, pcReqs)); + /* Check parameters. */ AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE); AssertPtrReturn(pcReqs, VERR_INVALID_POINTER); @@ -824,6 +869,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER); AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE); + rtFileAioCtxDump(pCtxInt); + int32_t cRequestsWaiting = ASMAtomicReadS32(&pCtxInt->cRequests); if (RT_UNLIKELY(cRequestsWaiting <= 0)) @@ -865,12 +912,16 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL } #endif + LogFlow(("Waiting for %d requests to complete\n", pCtxInt->iFirstFree)); + rtFileAioCtxDump(pCtxInt); + ASMAtomicXchgBool(&pCtxInt->fWaiting, true); int rcPosix = aio_suspend((const struct aiocb * const *)pCtxInt->apReqs, pCtxInt->iFirstFree, pTimeout); ASMAtomicXchgBool(&pCtxInt->fWaiting, false); if (rcPosix < 0) { + LogFlow(("aio_suspend failed %d nent=%u\n", errno, pCtxInt->iFirstFree)); /* Check that this is an external wakeup event. */ if (errno == EINTR) rc = rtFileAioCtxProcessEvents(pCtxInt); @@ -983,6 +1034,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL Assert(pCtxInt->hThreadWait == RTThreadSelf()); ASMAtomicWriteHandle(&pCtxInt->hThreadWait, NIL_RTTHREAD); + rtFileAioCtxDump(pCtxInt); + return rc; } |