summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/r3/posix/fileaio-posix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Runtime/r3/posix/fileaio-posix.cpp')
-rw-r--r--src/VBox/Runtime/r3/posix/fileaio-posix.cpp97
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;
}