PDMAsyncCompletionFileNormal.cpp revision 1d650736ebf4152a341805561a3a86d79769171b
/* $Id$ */
/** @file
* PDM Async I/O - Transport data asynchronous in R3 using EMT.
* Async File I/O manager.
*/
/*
* Copyright (C) 2006-2008 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#include "PDMAsyncCompletionFileInternal.h"
{
int rc = VINF_SUCCESS;
if (rc == VERR_OUT_OF_RANGE)
rc = RTFileAioCtxCreate(&pAioMgr->hAioCtx, 128); /* @todo: Find better solution wrt. the request number*/
return rc;
}
{
}
/**
* Error handler which will create the failsafe managers and destroy the failed I/O manager.
*
* @returns VBox status code
* @param pAioMgr The I/O manager the error ocurred on.
* @param rc The error code.
*/
{
AssertMsgFailed(("Implement\n"));
return VINF_SUCCESS;
}
{
unsigned cRequests = 0;
int rc = VINF_SUCCESS;
PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass;
/* Go through the list and queue the requests until we get a flush request */
{
switch (pTaskFile->enmTransferType)
{
{
/* If there is no data transfer request this flush request finished immediately. */
{
/* Task completed. Notify owner */
}
else
{
if (pTaskHead)
{
/* Add the rest of the tasks to the pending list */
{
}
else
{
}
/* Update the tail. */
}
}
break;
}
{
do
{
/* Check if the alignment requirements are met. */
{
/* Create bounce buffer. */
pSeg->fBounceBuffer = true;
/** @todo: I think we need something like a RTMemAllocAligned method here.
* Current assumption is that the maximum alignment is 4096byte
* (GPT disk on Windows)
* so we can use RTMemPageAlloc here.
*/
}
else
pSeg->fBounceBuffer = false;
("AIO: Alignment restrictions not met!\n"));
else
cRequests++;
{
if (RT_FAILURE(rc))
{
/* @todo implement */
AssertMsgFailed(("Implement\n"));
}
cRequests = 0;
}
break;
}
default:
}
}
if (cRequests)
{
if (RT_FAILURE(rc))
{
/* @todo implement */
AssertMsgFailed(("Implement\n"));
}
}
return rc;
}
/**
* Adds all pending requests for the given endpoint
* until a flush request is encountered or there is no
* request anymore.
*
* @returns VBox status code.
* @param pAioMgr The async I/O manager for the endpoint
* @param pEndpoint The endpoint to get the requests from.
*/
{
int rc = VINF_SUCCESS;
/* Check the pending list first */
{
/*
* Clear the list as the processing routine will insert them into the list
* again if it gets aflush request.
*/
}
{
/* Now the request queue. */
if (pTasksHead)
{
}
}
return rc;
}
{
int rc = VINF_SUCCESS;
bool fNotifyWaiter = true;
switch (pAioMgr->enmBlockingEvent)
{
{
PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointNew = (PPDMASYNCCOMPLETIONENDPOINTFILE)ASMAtomicReadPtr((void * volatile *)&pAioMgr->BlockingEventData.AddEndpoint.pEndpoint);
if (pAioMgr->pEndpointsHead)
/* Assign the completion point to this file. */
break;
}
{
PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointRemove = (PPDMASYNCCOMPLETIONENDPOINTFILE)ASMAtomicReadPtr((void * volatile *)&pAioMgr->BlockingEventData.RemoveEndpoint.pEndpoint);
if (pPrev)
else
if (pNext)
/* Make sure that there is no request pending on this manager for the endpoint. */
{
/* Reopen the file so that the new endpoint can reassociate with the file */
}
else
{
/* Mark the endpoint as removed and wait until all pending requests are finished. */
pEndpointRemove->fRemovedOrClosed = true;
/* We can't release the waiting thread here. */
fNotifyWaiter = false;
}
break;
}
{
PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointClose = (PPDMASYNCCOMPLETIONENDPOINTFILE)ASMAtomicReadPtr((void * volatile *)&pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint);
/* Make sure all tasks finished. Process the queues a last time first. */
{
/* Reopen the file to deassociate it from the endpoint. */
}
else
{
/* Mark the endpoint as removed and wait until all pending requests are finished. */
pEndpointClose->fRemovedOrClosed = true;
/* We can't release the waiting thread here. */
fNotifyWaiter = false;
}
break;
}
break;
break;
default:
}
if (fNotifyWaiter)
{
/* Release the waiting thread. */
}
return rc;
}
/** Helper macro for checking for error codes. */
if (RT_FAILURE(rc)) \
{\
return rc2;\
}
/**
* The normal I/O manager using the RTFileAio* API
*
* @returns VBox status code.
* @param ThreadSelf Handle of the thread.
* @param pvUser Opaque user data.
*/
{
int rc = VINF_SUCCESS;
{
LogFlow(("Got woken up\n"));
/* Check for an external blocking event first. */
if (pAioMgr->fBlockingEventPending)
{
}
/* Check the assigned endpoints for new tasks if there isn't a flush request active at the moment. */
while (pEndpoint)
{
{
}
}
while (pAioMgr->cRequestsActive)
{
uint32_t cReqsCompleted = 0;
for (uint32_t i = 0; i < cReqsCompleted; i++)
{
size_t cbTransfered = 0;
("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rc, cbTransfered));
if (pTaskSeg->fBounceBuffer)
{
}
{
/* Free all segments. */
while (pSegCurr)
{
}
/* Task completed. Notify owner */
}
/*
* If there is no request left on the endpoint but a flush request is set
* it completed now and we notify the owner.
* Furthermore we look for new requests and continue.
*/
{
}
if (!pEndpoint->fRemovedOrClosed)
{
{
/* Check if there are events on the endpoint. */
}
}
{
pEndpoint->fRemovedOrClosed = false;
/* Release the waiting thread. */
}
}
/* Check for an external blocking event before we go to sleep again. */
if (pAioMgr->fBlockingEventPending)
{
}
}
}
return rc;
}