aiomgr.cpp revision 13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * IPRT - Async I/O manager.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Copyright (C) 2013 Oracle Corporation
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * available from http://www.virtualbox.org. This file is free software;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * you can redistribute it and/or modify it under the terms of the GNU
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * General Public License (GPL) as published by the Free Software
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * The contents of this file may alternatively be used under the terms
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * of the Common Development and Distribution License Version 1.0
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * VirtualBox OSE distribution, in which case the provisions of the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * CDDL are applicable instead of those of the GPL.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * You may elect to license modified versions of this file under the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * terms and conditions of either the GPL or the CDDL or both.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Header Files *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Structures and Typedefs *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Pointer to an internal async I/O file instance. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Blocking event types.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Invalid tye */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** No event pending. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** A file is added to the manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** A file is about to be closed. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** The async I/O manager is shut down. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** 32bit hack */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Async I/O manager instance data.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsynctypedef struct RTAIOMGRINT
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Magic value. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Reference count. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Async I/O context handle. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** async I/O thread. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** List of files assigned to this manager. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Number of requests active currently. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Number of maximum requests active. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Memory cache for requests. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Critical section protecting the blocking event handling. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Event semaphore for blocking external events.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * The caller waits on it until the async I/O manager
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * finished processing the event. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Blocking event type */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Event type data */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** The file to be added */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** The file to be closed */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Pointer to an internal async I/O manager instance. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Async I/O manager file instance data.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Magic value. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Reference count. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Flags. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** File handle. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** async I/O manager this file belongs to. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Work queue for new requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Completion callback for this file. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Data for exclusive use by the assigned async I/O manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** List node of assigned files for a async I/O manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** List of requests waiting for submission. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Number of requests currently being processed for this endpoint
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * (excluded flush requests). */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Flag whether the file is closed. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Request type.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Invalid request type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Read reques type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Write request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Flush request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Prefetech request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** 32bit hack. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Pointer to a reques type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Async I/O manager request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsynctypedef struct RTAIOMGRREQ
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Atomic queue work item. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Node for a waiting list. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Request flags. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Transfer type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Assigned file request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** File the request belongs to. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Opaque user data. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Start offset */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Data segment. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** When non-zero the segment uses a bounce buffer because the provided buffer
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * doesn't meet host requirements. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Pointer to the used bounce buffer if any. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Start offset in the bounce buffer to copy from. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Pointer to a I/O manager request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Flag whether the request was prepared already. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Defined Constants And Macros *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn((a_hAioMgr)->u32Magic == RTAIOMGR_MAGIC, (a_rc)); \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync } while (0)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#define RTAIOMGR_VALID_RETURN(a_hAioMgr) RTAIOMGR_VALID_RETURN_RC((hAioMgr), VERR_INVALID_HANDLE)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Validates a handle and returns (void) if not valid. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturnVoid((a_hAioMgr)->u32Magic == RTAIOMGR_MAGIC); \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync } while (0)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Internal Functions *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrReqsEnqueue(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Removes an endpoint from the currently assigned manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns TRUE if there are still requests pending on the current manager for this endpoint.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * FALSE otherwise.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pEndpointRemove The endpoint to remove.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic bool rtAioMgrFileRemove(PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Make sure that there is no request pending on this manager for the endpoint. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return false;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Allocate a new I/O request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns Pointer to the allocated request or NULL if out of memory.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic PRTAIOMGRREQ rtAioMgrReqAlloc(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return (PRTAIOMGRREQ)RTMemCacheAlloc(pThis->hMemCacheReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Frees an I/O request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns nothing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReq The request to free.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrReqFree(PRTAIOMGRINT pThis, PRTAIOMGRREQ pReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTMemPageFree(pReq->pvBounceBuffer, pReq->cbBounceBuffer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrReqCompleteRc(PRTAIOMGRINT pThis, PRTAIOMGRREQ pReq,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * It is possible that the request failed on Linux with kernels < 2.6.23
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * if the passed buffer was allocated with remap_pfn_range or if the file
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * is on an NFS endpoint which does not support async and direct I/O at the same time.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * The endpoint will be migrated to a failsafe manager in case a request fails.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->pfnReqCompleted(pFile, rcReq, pReq->pvUser);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Restart an incomplete transfer.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * This usually means that the request will return an error now
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * but to get the cause of the error (disk full, file too big, I/O error, ...)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * the transfer needs to be continued.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_UNLIKELY( cbTransfered < pReq->DataSeg.cbSeg
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart = (pReq->off & ~((RTFOFF)512-1)) + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cbToTransfer = pReq->cbBounceBuffer - cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pbBuf = (uint8_t *)pReq->pvBounceBuffer + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pbBuf = (uint8_t *)pReq->DataSeg.pvSeg + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareRead(pReq->hReqIo, pFile->hFile, offStart,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Invalid transfer type\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareWrite(pReq->hReqIo, pFile->hFile, offStart,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, &pReq->hReqIo, 1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else if (pReq->enmType == RTAIOMGRREQTYPE_PREFETCH)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync memcpy(((uint8_t *)pReq->pvBounceBuffer) + pReq->offBounceBuffer,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Write it now. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbToTransfer = RT_ALIGN_Z(pReq->DataSeg.cbSeg + (pReq->off - offStart), 512);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareWrite(pReq->hReqIo, pFile->hFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart, pReq->pvBounceBuffer, cbToTransfer, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, &pReq->hReqIo, 1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ((uint8_t *)pReq->pvBounceBuffer) + pReq->offBounceBuffer,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Call completion callback */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->pfnReqCompleted(pFile, rcReq, pReq->pvUser);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync } /* request completed successfully */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Wrapper around rtAioMgrReqCompleteRc().
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrReqComplete(PRTAIOMGRINT pThis, RTFILEAIOREQ hReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rcReq = RTFileAioReqGetRC(hReq, &cbTransfered);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)RTFileAioReqGetUser(hReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqCompleteRc(pThis, pReq, rcReq, cbTransfered);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Wrapper around RTFIleAioCtxSubmit() which is also doing error handling.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrReqsEnqueue(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTFileAioCtxSubmit(pThis->hAioCtx, pahReqs, cReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Append any not submitted task to the waiting list. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)RTFileAioReqGetUser(pahReqs[i]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListAppend(&pFile->AioMgr.ListWaitingReqs, &pReq->NodeWaitingList);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else /* Another kind of error happened (full disk, ...) */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* An error happened. Find out which one caused the error and resubmit all other tasks. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)RTFileAioReqGetUser(pahReqs[i]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* We call ourself again to do any error handling which might come up now. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, &pahReqs[i], 1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Adds a list of requests to the waiting list.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns nothing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file instance to add the requests to.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReqsHead The head of the request list to add.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrFileAddReqsToWaitingList(PRTAIOMGRFILEINT pFile, PRTAIOMGRREQ pReqsHead)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReqsHead = (PRTAIOMGRREQ)pReqsHead->WorkItem.pNext;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListAppend(&pFile->AioMgr.ListWaitingReqs, &pReqCur->NodeWaitingList);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Prepare the native I/o request ensuring that all alignment prerequisites of
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * the host are met.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT statuse code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReq The request to prepare.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrReqPrepareNonBuffered(PRTAIOMGRFILEINT pFile, PRTAIOMGRREQ pReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbToTransfer = RT_ALIGN_Z(pReq->DataSeg.cbSeg + (pReq->off - offStart), 512);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync bool fAlignedReq = cbToTransfer == pReq->DataSeg.cbSeg
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Check if the alignment requirements are met.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Offset, transfer size and buffer address
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * need to be on a 512 boundary.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: || ((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) != (RTR3UINTPTR)pvBuf) */)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Create bounce buffer. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(pReq->off >= offStart, ("Overflow in calculation off=%llu offStart=%llu\n",
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: I think we need something like a RTMemAllocAligned method here.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Current assumption is that the maximum alignment is 4096byte
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * (GPT disk on Windows)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * so we can use RTMemPageAlloc here.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pvBounceBuffer = RTMemPageAlloc(cbToTransfer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if ( RT_UNLIKELY(cbToTransfer != pReq->DataSeg.cbSeg)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* We have to fill the buffer first before we can update the data. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync memcpy(pvBuf, pReq->DataSeg.pvSeg, pReq->DataSeg.cbSeg);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareWrite(pReq->hReqIo, pFile->hFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else /* Read or prefetch request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareRead(pReq->hReqIo, pFile->hFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Prepare a new request for enqueuing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReq The request to prepare.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param phReqIo Where to store the handle to the native I/O request on success.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrPrepareReq(PRTAIOMGRREQ pReq, PRTFILEAIOREQ phReqIo)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareFlush(pReq->hReqIo, pFile->hFile, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsgFailed(("Invalid transfer type %d\n", pReq->enmType));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync } /* switch transfer type */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Prepare newly submitted requests for processing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file instance.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReqsNew The list of new requests to prepare.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrPrepareNewReqs(PRTAIOMGRINT pThis,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync unsigned cRequests = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Go through the list and queue the requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && (pThis->cReqsActive + cRequests < pThis->cReqsActiveMax)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pCurr->pFile) && (pCurr->pFile == pFile),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Files do not match\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(!(pCurr->fFlags & RTAIOMGRREQ_FLAGS_PREPARED),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Request on the new list is already prepared\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrPrepareReq(pCurr, &apReqs[cRequests]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Queue the requests if the array is full. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Add the rest of the tasks to the pending list */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Insufficient resources are not fatal. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Queues waiting requests.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to get the requests from.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrQueueWaitingReqs(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync unsigned cRequests = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Go through the list and queue the requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListForEachSafe(&pFile->AioMgr.ListWaitingReqs, pReqIt, pReqItNext, RTAIOMGRREQ, NodeWaitingList)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pReqIt->pFile) && (pReqIt->pFile == pFile),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Files do not match\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!(pReqIt->fFlags & RTAIOMGRREQ_FLAGS_PREPARED))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrPrepareReq(pReqIt, &apReqs[cRequests]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Queue the requests if the array is full. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Insufficient resources are not fatal. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Adds all pending requests for the given file.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to get the requests from.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrQueueReqs(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Check the pending list first */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!RTListIsEmpty(&pFile->AioMgr.ListWaitingReqs))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReqsNew = (PRTAIOMGRREQ)RTQueueAtomicRemoveAll(&pFile->QueueReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrPrepareNewReqs(pThis, pFile, pReqsNew);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Checks all files for new requests.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListForEach(&pThis->ListFiles, pIt, RTAIOMGRFILEINT, AioMgr.NodeAioMgrFiles)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Process a blocking event from the outside.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrProcessBlockingEvent(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Nothing to do. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = ASMAtomicReadPtrT(&pThis->BlockingEventData.pFileAdd, PRTAIOMGRFILEINT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pFile), ("Adding file event without a file to add\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListAppend(&pThis->ListFiles, &pFile->AioMgr.NodeAioMgrFiles);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = ASMAtomicReadPtrT(&pThis->BlockingEventData.pFileClose, PRTAIOMGRFILEINT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pFile), ("Close file event without a file to close\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Make sure all requests finished. Process the queues a last time first. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertReleaseMsgFailed(("Invalid event type %d\n", pThis->enmBlockingEvent));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Release the waiting thread. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * async I/O manager worker loop.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @returns IPRT status code.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param hThreadSelf The thread handle this worker belongs to.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param pvUser Opaque user data (Pointer to async I/O manager instance).
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncstatic DECLCALLBACK(int) rtAioMgrWorker(RTTHREAD hThreadSelf, void *pvUser)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync bool fRunning = true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioCtxWait(pThis->hAioCtx, 1, RT_INDEFINITE_WAIT, &ahReqsCompleted[0],
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Process external event. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Something bad happened. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Requests completed. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Check files for new requests and queue waiting requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Wakes up the async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Waits until the async I/O manager handled the given event.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param enmEvent The event to pass to the manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrWaitForBlockingEvent(PRTAIOMGRINT pThis, RTAIOMGREVENT enmEvent)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync Assert(pThis->enmBlockingEvent == RTAIOMGREVENT_NO_EVENT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteU32((volatile uint32_t *)&pThis->enmBlockingEvent, enmEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Wakeup the async I/O manager */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Wait for completion. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTSemEventWait(pThis->hEventSemBlock, RT_INDEFINITE_WAIT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteU32((volatile uint32_t *)&pThis->enmBlockingEvent, RTAIOMGREVENT_NO_EVENT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Add a given file to the given I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to add.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrAddFile(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Update the assigned I/O manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTCritSectEnter(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWritePtr(&pThis->BlockingEventData.pFileAdd, pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrWaitForBlockingEvent(pThis, RTAIOMGREVENT_FILE_ADD);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteNullPtr(&pThis->BlockingEventData.pFileAdd);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Removes a given file from the given I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to remove.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrCloseFile(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTCritSectEnter(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWritePtr(&pThis->BlockingEventData.pFileClose, pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrWaitForBlockingEvent(pThis, RTAIOMGREVENT_FILE_CLOSE);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteNullPtr(&pThis->BlockingEventData.pFileClose);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Process a shutdown event.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager to shut down.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTCritSectEnter(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrWaitForBlockingEvent(pThis, RTAIOMGREVENT_SHUTDOWN);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Destroys an async I/O manager.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @returns nothing.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param pThis The async I/O manager instance to destroy.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = RTThreadWait(pThis->hThread, RT_INDEFINITE_WAIT, NULL);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Queues a new request for processing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrFileQueueReq(PRTAIOMGRFILEINT pThis, PRTAIOMGRREQ pReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTQueueAtomicInsert(&pThis->QueueReqs, &pReq->WorkItem);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Destroys an async I/O manager file.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @returns nothing.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param pThis The async I/O manager file.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncstatic void rtAioMgrFileDestroy(PRTAIOMGRFILEINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Queues a new I/O request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param hAioMgrFile The I/O manager file handle.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param off Start offset of the I/o request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pSgBuf Data S/G buffer.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param cbIo How much to transfer.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvUser Opaque user data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param enmType I/O direction type (read/write).
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrFileIoReqCreate(RTAIOMGRFILE hAioMgrFile, RTFOFF off, PRTSGBUF pSgBuf,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbIo, void *pvUser, RTAIOMGRREQTYPE enmType)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbSeg = RTSgBufSegArrayCreate(pSgBuf, &pReq->DataSeg, &cSeg, cbIo);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: Real S/G buffer support. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Request constructor for the memory cache.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param hMemCache The cache handle.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvObj The memory object that should be initialized.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvUser The user argument.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic DECLCALLBACK(int) rtAioMgrReqCtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Request destructor for the memory cache.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param hMemCache The cache handle.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvObj The memory object that should be destroyed.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvUser The user argument.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic DECLCALLBACK(void) rtAioMgrReqDtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrCreate(PRTAIOMGR phAioMgr, uint32_t cReqsMax)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(cReqsMax > 0, VERR_INVALID_PARAMETER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis = (PRTAIOMGRINT)RTMemAllocZ(sizeof(RTAIOMGRINT));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTMemCacheCreate(&pThis->hMemCacheReqs, sizeof(RTAIOMGRREQ),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync 0, UINT32_MAX, rtAioMgrReqCtor, rtAioMgrReqDtor, NULL, 0);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioCtxCreate(&pThis->hAioCtx, cReqsMax == UINT32_MAX
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTThreadCreateF(&pThis->hThread, rtAioMgrWorker, pThis, 0, RTTHREADTYPE_IO,
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGR_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs > 1 && cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGR_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileCreate(RTAIOMGR hAioMgr, RTFILE hFile, PFNRTAIOMGRREQCOMPLETE pfnReqComplete,
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hAioMgr != NIL_RTAIOMGR, VERR_INVALID_HANDLE);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(pfnReqComplete, VERR_INVALID_POINTER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(phAioMgrFile, VERR_INVALID_POINTER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis = (PRTAIOMGRFILEINT)RTMemAllocZ(sizeof(RTAIOMGRFILEINT));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = RTFileAioCtxAssociateWithFile(pThis->pAioMgr->hAioCtx, hFile);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(uint32_t) RTAioMgrFileRetain(RTAIOMGRFILE hAioMgrFile)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hAioMgrFile != NIL_RTAIOMGRFILE, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGRFILE_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs > 1 && cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(uint32_t) RTAioMgrFileRelease(RTAIOMGRFILE hAioMgrFile)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGRFILE_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileRead(RTAIOMGRFILE hAioMgrFile, RTFOFF off,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rtAioMgrFileIoReqCreate(hAioMgrFile, off, pSgBuf, cbRead, pvUser,
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileWrite(RTAIOMGRFILE hAioMgrFile, RTFOFF off,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rtAioMgrFileIoReqCreate(hAioMgrFile, off, pSgBuf, cbWrite, pvUser,