VirtualBox

Changeset 19562 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
May 10, 2009 9:44:16 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
47117
Message:

Runtime/Aio: Change API again

  • pcReqs in RTFileAioCtxSubmit is useless because it does not specify which request fails. Removed it again and made it possible to get the state of a request through RTFileAioReqGetRC()
  • Introduce request states for the first point and to catch more errors using the API before a system dependent call is made to return the same error codes one every system for the same cause.
  • Add RTFileAioGetLimits to get global limits and indication for AIO support.
  • General cleanups and fixes
Location:
trunk/src/VBox/Runtime/r3
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp

    r19187 r19562  
    4747#include <sys/event.h>
    4848#include <sys/time.h>
     49#include <sys/sysctl.h>
    4950#include <aio.h>
    5051#include <errno.h>
     
    8485     *  element. */
    8586    struct aiocb           AioCB;
     87    /** Current state the request is in. */
     88    RTFILEAIOREQSTATE      enmState;
    8689    /** Flag whether this is a flush request. */
    8790    bool                   fFlush;
     
    107110#define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64
    108111
     112RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits)
     113{
     114    int rcBSD = 0;
     115    AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER);
     116
     117    /*
     118     * The AIO API is implemented in a kernel module which is not
     119     * loaded by default.
     120     * If it is loaded there are additional sysctl parameters.
     121     */
     122    int cReqsOutstandingMax = 0;
     123    size_t cbParameter = sizeof(int);
     124
     125    rcBSD = sysctlbyname("vfs.aio.max_aio_per_proc", /* name */
     126                         &cReqsOutstandingMax,       /* Where to store the old value. */
     127                         &cbParameter,               /* Size of the memory pointed to. */
     128                         NULL,                       /* Where the new value is located. */
     129                         NULL);                      /* Where the size of the new value is stored. */
     130    if (rcBSD == -1)
     131    {
     132        /* ENOENT means the value is unknown thus the module is not loaded. */
     133        if (errno == ENOENT)
     134            return VERR_NOT_SUPPORTED;
     135        else
     136            return RTErrConvertFromErrno(errno);
     137    }
     138
     139    pAioLimits->cReqsOutstandingMax = cReqsOutstandingMax;
     140    pAioLimits->cbBufferAlignment   = 0;
     141
     142    return VINF_SUCCESS;
     143}
     144
    109145RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq)
    110146{
     
    120156    pReqInt->pCtxInt                   = NULL;
    121157    pReqInt->u32Magic                  = RTFILEAIOREQ_MAGIC;
     158    RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    122159
    123160    *phReq = (RTFILEAIOREQ)pReqInt;
     
    126163}
    127164
    128 RTDECL(void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
     165RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
    129166{
    130167    /*
     
    132169     */
    133170    if (hReq == NIL_RTFILEAIOREQ)
    134         return;
     171        return VINF_SUCCESS;
    135172    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    136     RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt);
     173    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     174    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    137175
    138176    /*
     
    141179    ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC);
    142180    RTMemFree(pReqInt);
     181    return VINF_SUCCESS;
    143182}
    144183
     
    156195    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    157196    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     197    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    158198    Assert(hFile != NIL_RTFILE);
    159199    AssertPtr(pvBuf);
     
    171211    pReqInt->pCtxInt              = NULL;
    172212    pReqInt->Rc                   = VERR_FILE_AIO_IN_PROGRESS;
     213    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
    173214
    174215    return VINF_SUCCESS;
     
    195236    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    196237    Assert(hFile != NIL_RTFILE);
     238    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    197239
    198240    pReqInt->fFlush           = true;
    199241    pReqInt->AioCB.aio_fildes = (int)hFile;
    200242    pReqInt->pvUser           = pvUser;
     243    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
    201244
    202245    return VINF_SUCCESS;
     
    215258    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    216259    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     260    RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);
     261
    217262
    218263    int rcBSD = aio_cancel(pReqInt->AioCB.aio_fildes, &pReqInt->AioCB);
     
    228273
    229274        ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests);
     275        pReqInt->Rc = VERR_FILE_AIO_CANCELED;
     276        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    230277        return VINF_SUCCESS;
    231278    }
     
    243290    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    244291    AssertPtrNull(pcbTransfered);
    245 
    246     if (  (pReqInt->Rc != VERR_FILE_AIO_IN_PROGRESS)
     292    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
     293    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
     294
     295    if (  (RT_SUCCESS(pReqInt->Rc))
    247296        && (pcbTransfered))
    248297        *pcbTransfered = pReqInt->cbTransfered;
     
    306355}
    307356
    308 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
     357RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
    309358{
    310359    /*
    311360     * Parameter validation.
    312361     */
    313     AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);
    314     *pcReqs = 0;
     362    int rc = VINF_SUCCESS;
    315363    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    316364    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
     
    330378        {
    331379            pReqInt = pahReqs[i];
    332             RTFILEAIOREQ_VALID_RETURN(pReqInt);
     380            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
     381            {
     382                /* Undo everything and stop submitting. */
     383                for (size_t iUndo = 0; iUndo < i; iUndo++)
     384                {
     385                    pReqInt = pahReqs[iUndo];
     386                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     387                    pReqInt->pCtxInt = NULL;
     388                    pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = 0;
     389                }
     390                rc = VERR_INVALID_HANDLE;
     391                break;
     392            }
    333393
    334394            pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = pCtxInt->iKQueue;
    335395            pReqInt->pCtxInt                                = pCtxInt;
     396            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);
    336397
    337398            if (pReqInt->fFlush)
     
    346407            rcBSD = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
    347408            if (RT_UNLIKELY(rcBSD < 0))
    348                 return RTErrConvertFromErrno(errno);
     409            {
     410                if (rcBSD == EAGAIN)
     411                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
     412                else
     413                    rc = RTErrConvertFromErrno(errno);
     414
     415                /* Check which requests got actually submitted and which not. */
     416                for (i = 0; i < cReqs; i++)
     417                {
     418                    pReqInt = pahReqs[i];
     419                    rcBSD = aio_error(&pReqInt->AioCB);
     420                    if (rcBSD == EINVAL)
     421                    {
     422                        /* Was not submitted. */
     423                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     424                        pReqInt->pCtxInt = NULL;
     425                    }
     426                    else if (rcBSD != EINPROGRESS)
     427                    {
     428                        /* The request encountered an error. */
     429                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
     430                        pReqInt->Rc = RTErrConvertFromErrno(rcBSD);
     431                        pReqInt->pCtxInt      = NULL;
     432                        pReqInt->cbTransfered = 0;
     433                    }
     434                }
     435                break;
     436            }
    349437
    350438            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
    351439            cReqs   -= cReqsSubmit;
    352440            pahReqs += cReqsSubmit;
    353             *pcReqs += cReqsSubmit;
    354441        }
    355442
     
    368455                 rcBSD = aio_fsync(O_SYNC, &pReqInt->AioCB);
    369456                 if (RT_UNLIKELY(rcBSD < 0))
    370                     return RTErrConvertFromErrno(errno);
     457                 {
     458                    RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
     459                    pReqInt->Rc = RTErrConvertFromErrno(errno);
     460                    pReqInt->cbTransfered = 0;
     461                    return pReqInt->Rc;
     462                 }
    371463
    372464                ASMAtomicIncS32(&pCtxInt->cRequests);
    373465                cReqs--;
    374466                pahReqs++;
    375                 *pcReqs++;
    376467            }
    377468        }
    378469    } while (cReqs);
    379470
    380     return VINF_SUCCESS;
     471    return rc;
    381472}
    382473
     
    447538        {
    448539            PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)aKEvents[i].udata;
     540            AssertPtr(pReqInt);
     541            Assert(pReqInt->u32Magic == RTFILEAIOREQ_MAGIC);
    449542
    450543            /*
     
    468561                pReqInt->cbTransfered = cbTransfered;
    469562            }
     563            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    470564            pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt;
    471565        }
  • trunk/src/VBox/Runtime/r3/linux/fileaio-linux.cpp

    r19371 r19562  
    190190     *  the structure! (see notes below) */
    191191    LNXKAIOIOCB           AioCB;
     192    /** Current state the request is in. */
     193    RTFILEAIOREQSTATE     enmState;
    192194    /** The I/O context this request is associated with. */
    193195    aio_context_t         AioContext;
    194196    /** Return code the request completed with. */
    195197    int                   Rc;
    196     /** Flag whether the request is in process or not. */
    197     bool                  fFinished;
    198198    /** Number of bytes actually trasnfered. */
    199199    size_t                cbTransfered;
     
    241241 * Submits an array of I/O requests to the kernel.
    242242 */
    243 DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB)
     243DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB, int *pcSubmitted)
    244244{
    245245    int rc = syscall(__NR_io_submit, AioContext, cReqs, ppIoCB);
     
    247247        return RTErrConvertFromErrno(errno);
    248248
     249    *pcSubmitted = rc;
     250
    249251    return VINF_SUCCESS;
    250252}
     
    276278}
    277279
     280RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits)
     281{
     282    int rc = VINF_SUCCESS;
     283    AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER);
     284
     285    /*
     286     * Check if the API is implemented by creating a
     287     * completion port.
     288     */
     289    aio_context_t AioContext = 0;
     290    rc = rtFileAsyncIoLinuxCreate(1, &AioContext);
     291    if (RT_FAILURE(rc))
     292        return rc;
     293
     294    rc = rtFileAsyncIoLinuxDestroy(AioContext);
     295    if (RT_FAILURE(rc))
     296        return rc;
     297
     298    /* Supported - fill in the limits. The alignment is the only restriction. */
     299    pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS;
     300    pAioLimits->cbBufferAlignment   = 512;
     301
     302    return VINF_SUCCESS;
     303}
     304
     305
    278306RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq)
    279307{
     
    287315        return VERR_NO_MEMORY;
    288316
    289     pReqInt->fFinished = false;
    290317    pReqInt->pCtxInt   = NULL;
    291318    pReqInt->u32Magic  = RTFILEAIOREQ_MAGIC;
     319    RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    292320
    293321    *phReq = (RTFILEAIOREQ)pReqInt;
     
    296324
    297325
    298 RTDECL(void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
     326RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
    299327{
    300328    /*
     
    302330     */
    303331    if (hReq == NIL_RTFILEAIOREQ)
    304         return;
     332        return VINF_SUCCESS;
    305333    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    306     RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt);
     334    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     335    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    307336
    308337    /*
     
    311340    ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC);
    312341    RTMemFree(pReqInt);
     342    return VINF_SUCCESS;
    313343}
    314344
     
    327357    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    328358    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     359    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    329360    Assert(hFile != NIL_RTFILE);
    330361    AssertPtr(pvBuf);
     
    342373    pReqInt->AioCB.pvUser      = pvUser;
    343374
    344     pReqInt->fFinished         = false;
    345375    pReqInt->pCtxInt           = NULL;
     376    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
    346377
    347378    return VINF_SUCCESS;
     
    370401    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    371402    AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
     403    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    372404
    373405    /** @todo: Flushing is not neccessary on Linux because O_DIRECT is mandatory
     
    397429    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    398430    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     431    RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);
    399432
    400433    LNXKAIOIOEVENT AioEvent;
     
    410443
    411444        ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests);
     445        pReqInt->Rc = VERR_FILE_AIO_CANCELED;
     446        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    412447        return VINF_SUCCESS;
    413448    }
     
    423458    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    424459    AssertPtrNull(pcbTransfered);
    425 
    426     if (!pReqInt->fFinished)
    427         return VERR_FILE_AIO_IN_PROGRESS;
     460    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
     461    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
    428462
    429463    if (    pcbTransfered
     
    509543}
    510544
    511 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
    512 {
     545RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
     546{
     547    int rc = VINF_SUCCESS;
     548
    513549    /*
    514550     * Parameter validation.
    515551     */
    516     AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);
    517     *pcReqs = 0;
    518552    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    519553    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
     
    521555    AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);
    522556    uint32_t i = cReqs;
     557    PRTFILEAIOREQINTERNAL pReqInt = NULL;
    523558
    524559    /*
     
    527562    while (i-- > 0)
    528563    {
    529         PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i];
    530         RTFILEAIOREQ_VALID_RETURN(pReqInt);
     564        pReqInt = pahReqs[i];
     565        if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
     566        {
     567            /* Undo everything and stop submitting. */
     568            size_t iUndo = cReqs;
     569            while (iUndo-- > i)
     570            {
     571                pReqInt = pahReqs[iUndo];
     572                RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     573                pReqInt->pCtxInt = NULL;
     574            }
     575            return VERR_INVALID_HANDLE;
     576        }
    531577
    532578        pReqInt->AioContext = pCtxInt->AioContext;
    533579        pReqInt->pCtxInt    = pCtxInt;
     580        RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);
    534581    }
    535582
    536     /*
    537      * Add the submitted requests to the counter
    538      * to prevent destroying the context while
    539      * it is still used.
    540      */
    541     ASMAtomicAddS32(&pCtxInt->cRequests, cReqs);
    542 
    543     /*
    544      * We cast phReqs to the Linux iocb structure to avoid copying the requests
    545      * into a temporary array. This is possible because the iocb structure is
    546      * the first element in the request structure (see PRTFILEAIOCTXINTERNAL).
    547      */
    548     int rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, (PLNXKAIOIOCB *)pahReqs);
    549     if (RT_FAILURE(rc))
    550         ASMAtomicSubS32(&pCtxInt->cRequests, cReqs);
    551     else
    552         *pcReqs = cReqs;
     583    do
     584    {
     585        /*
     586         * We cast pahReqs to the Linux iocb structure to avoid copying the requests
     587         * into a temporary array. This is possible because the iocb structure is
     588         * the first element in the request structure (see PRTFILEAIOCTXINTERNAL).
     589         */
     590        int cReqsSubmitted = 0;
     591        rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs,
     592                                      (PLNXKAIOIOCB *)pahReqs,
     593                                      &cReqsSubmitted);
     594        if (RT_FAILURE(rc))
     595        {
     596            /*
     597             * We encountered an error.
     598             * This means that the first IoCB
     599             * is not correctly initialized
     600             * (invalid buffer alignment or bad file descriptor).
     601             * Revert every request into the prepared state except
     602             * the first one which will switch to completed.
     603             * Another reason could be insuffidient ressources.
     604             */
     605            i = cReqs;
     606            while (i-- > 0)
     607            {
     608                /* Already validated. */
     609                pReqInt = pahReqs[i];
     610                pReqInt->pCtxInt    = NULL;
     611                pReqInt->AioContext = 0;
     612                RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     613            }
     614
     615            if (rc == VERR_TRY_AGAIN)
     616                return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
     617            else
     618            {
     619                /* The first request failed. */
     620                pReqInt = pahReqs[0];
     621                RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
     622                pReqInt->Rc = rc;
     623                pReqInt->cbTransfered = 0;
     624                return rc;
     625            }
     626        }
     627
     628        /* Advance. */
     629        cReqs   -= cReqsSubmitted;
     630        pahReqs += cReqsSubmitted;
     631        ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted);
     632
     633    } while (cReqs);
    553634
    554635    return rc;
     
    643724
    644725            /* Mark the request as finished. */
    645             pReqInt->fFinished = true;
     726            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    646727
    647728            pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt;
  • trunk/src/VBox/Runtime/r3/posix/fileaio-posix.cpp

    r19370 r19562  
    4545#include "internal/fileaio.h"
    4646
     47#if defined(RT_OS_DARWIN)
     48# include <sys/types.h>
     49# include <sys/sysctl.h> /* for sysctlbyname */
     50#endif
    4751#include <aio.h>
    4852#include <errno.h>
     
    7074    /** Next element in the chain. */
    7175    struct RTFILEAIOREQINTERNAL *pNext;
     76    /** Previous element in the chain. */
     77    struct RTFILEAIOREQINTERNAL *pPrev;
     78    /** Current state the request is in. */
     79    RTFILEAIOREQSTATE            enmState;
    7280    /** Flag whether this is a flush request. */
    7381    bool                         fFlush;
     
    183191                pReqHead = pReqHead->pNext;
    184192
    185                 /* Clear pointer to next element just for safety. */
     193                /* Clear pointer to next and previous element just for safety. */
    186194                pCtxInt->apReqs[pCtxInt->iFirstFree]->pNext = NULL;
     195                pCtxInt->apReqs[pCtxInt->iFirstFree]->pPrev = NULL;
    187196                pCtxInt->iFirstFree++;
    188197                Assert(pCtxInt->iFirstFree <= pCtxInt->cMaxRequests);
     
    210219}
    211220
     221RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits)
     222{
     223    int rcBSD = 0;
     224    AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER);
     225
     226#if defined(RT_OS_DARWIN)
     227    int cReqsOutstandingMax = 0;
     228    size_t cbParameter = sizeof(int);
     229
     230    rcBSD = sysctlbyname("kern.aioprocmax",     /* name */
     231                         &cReqsOutstandingMax,  /* Where to store the old value. */
     232                         &cbParameter,          /* Size of the memory pointed to. */
     233                         NULL,                  /* Where the new value is located. */
     234                         NULL);                 /* Where the size of the new value is stored. */
     235    if (rcBSD == -1)
     236        return RTErrConvertFromErrno(errno);
     237
     238    pAioLimits->cReqsOutstandingMax = cReqsOutstandingMax;
     239    pAioLimits->cbBufferAlignment   = 0;
     240#else
     241    pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS;
     242    pAioLimits->cbBufferAlignment   = 0;
     243#endif
     244
     245    return VINF_SUCCESS;
     246}
     247
    212248RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq)
    213249{
     
    220256    pReqInt->pCtxInt  = NULL;
    221257    pReqInt->u32Magic = RTFILEAIOREQ_MAGIC;
     258    RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    222259
    223260    *phReq = (RTFILEAIOREQ)pReqInt;
     
    227264
    228265
    229 RTDECL(void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
     266RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
    230267{
    231268    /*
     
    233270     */
    234271    if (hReq == NIL_RTFILEAIOREQ)
    235         return;
     272        return VINF_SUCCESS;
    236273    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    237     RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt);
     274    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     275    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    238276
    239277    /*
     
    242280    ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC);
    243281    RTMemFree(pReqInt);
     282    return VINF_SUCCESS;
    244283}
    245284
     
    257296    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    258297    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     298    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    259299    Assert(hFile != NIL_RTFILE);
    260300    AssertPtr(pvBuf);
     
    271311    pReqInt->pCtxInt              = NULL;
    272312    pReqInt->Rc                   = VERR_FILE_AIO_IN_PROGRESS;
     313    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
    273314
    274315    return VINF_SUCCESS;
     
    297338
    298339    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     340    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    299341    Assert(hFile != NIL_RTFILE);
    300342
     
    302344    pReqInt->AioCB.aio_fildes = (int)hFile;
    303345    pReqInt->pvUser           = pvUser;
     346    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
    304347
    305348    return VINF_SUCCESS;
     
    320363    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    321364    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     365    RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);
    322366
    323367    ASMAtomicXchgBool(&pReqInt->fCanceled, true);
     
    343387
    344388        ASMAtomicWritePtr((void* volatile*)&pCtxInt->pReqToCancel, NULL);
     389        pReqInt->Rc = VERR_FILE_AIO_CANCELED;
     390        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    345391        return VINF_SUCCESS;
    346392    }
     
    358404    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    359405    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     406    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
     407    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
    360408    AssertPtrNull(pcbTransfered);
    361409
    362     if (  (pReqInt->Rc != VERR_FILE_AIO_IN_PROGRESS)
     410    if (  (RT_SUCCESS(pReqInt->Rc))
    363411        && (pcbTransfered))
    364412        *pcbTransfered = pReqInt->cbTransfered;
     
    425473}
    426474
    427 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
     475RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
    428476{
    429477    int rc = VINF_SUCCESS;
     
    452500        {
    453501            pReqInt = pahReqs[i];
    454             RTFILEAIOREQ_VALID_RETURN(pReqInt);
     502            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
     503            {
     504                /* Undo everything and stop submitting. */
     505                for (size_t iUndo = 0; iUndo < i; iUndo++)
     506                {
     507                    pReqInt = pahReqs[iUndo];
     508                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     509                    pReqInt->pCtxInt = NULL;
     510
     511                    /* Unlink from the list again. */
     512                    PRTFILEAIOREQINTERNAL pNext, pPrev;
     513                    pNext = pReqInt->pNext;
     514                    pPrev = pReqInt->pPrev;
     515                    if (pNext)
     516                        pNext->pPrev = pPrev;
     517                    if (pPrev)
     518                        pPrev->pNext = pNext;
     519                    else
     520                        pHead = pNext;
     521                }
     522                rc = VERR_INVALID_HANDLE;
     523                break;
     524            }
    455525
    456526            pReqInt->pCtxInt = pCtxInt;
     
    458528            /* Link them together. */
    459529            pReqInt->pNext = pHead;
     530            if (pHead)
     531                pHead->pPrev = pReqInt;
     532            pReqInt->pPrev = NULL;
    460533            pHead = pReqInt;
     534            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);
    461535
    462536            if (pReqInt->fFlush)
     
    472546            if (RT_UNLIKELY(rcPosix < 0))
    473547            {
    474                 rc = RTErrConvertFromErrno(errno);
     548                if (rcPosix == EAGAIN)
     549                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
     550                else
     551                    rc = RTErrConvertFromErrno(errno);
     552
     553                /* Check which ones were not submitted. */
     554                for (i = 0; i < cReqs; i++)
     555                {
     556                    pReqInt = pahReqs[i];
     557                    rcPosix = aio_error(&pReqInt->AioCB);
     558                    if (rcPosix != EINPROGRESS)
     559                    {
     560                        if (rcPosix == EINVAL)
     561                        {
     562                            /* Was not submitted. */
     563                            RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     564                        }
     565                        else
     566                        {
     567                            /* An error occured. */
     568                            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
     569                            pReqInt->Rc = RTErrConvertFromErrno(rcPosix);
     570                            pReqInt->cbTransfered = 0;
     571                        }
     572                        /* Unlink from the list. */
     573                        PRTFILEAIOREQINTERNAL pNext, pPrev;
     574                        pNext = pReqInt->pNext;
     575                        pPrev = pReqInt->pPrev;
     576                        if (pNext)
     577                            pNext->pPrev = pPrev;
     578                        if (pPrev)
     579                            pPrev->pNext = pNext;
     580                        else
     581                            pHead = pNext;
     582                    }
     583                }
     584
    475585                break;
    476586            }
     
    479589            cReqs   -= cReqsSubmit;
    480590            pahReqs += cReqsSubmit;
    481             *pcReqs += cReqsSubmit;
    482591        }
    483592
     
    488597            RTFILEAIOREQ_VALID_RETURN(pReqInt);
    489598
    490             if (pReqInt->fFlush)
     599            Assert(pReqInt->fFlush);
     600
     601            /*
     602             * lio_listio does not work with flush requests so
     603             * we have to use aio_fsync directly.
     604             */
     605            rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB);
     606            if (RT_UNLIKELY(rcPosix < 0))
    491607            {
    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++;
     608                rc = RTErrConvertFromErrno(errno);
     609                RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
     610                pReqInt->Rc = rc;
     611                pReqInt->cbTransfered = 0;
     612
     613                /* Unlink from the list. */
     614                PRTFILEAIOREQINTERNAL pNext, pPrev;
     615                pNext = pReqInt->pNext;
     616                pPrev = pReqInt->pPrev;
     617                if (pNext)
     618                    pNext->pPrev = pPrev;
     619                if (pPrev)
     620                    pPrev->pNext = pNext;
     621                else
     622                    pHead = pNext;
     623                break;
    507624            }
     625
     626            ASMAtomicIncS32(&pCtxInt->cRequests);
     627            cReqs--;
     628            pahReqs++;
    508629        }
    509630    } while (cReqs);
     
    625746                        pReq->Rc = RTErrConvertFromErrno(rcReq);
    626747
     748                    /* Mark the request as finished. */
     749                    RTFILEAIOREQ_SET_STATE(pReq, COMPLETED);
    627750                    cDone++;
    628751
  • trunk/src/VBox/Runtime/r3/win/fileaio-win.cpp

    r19186 r19562  
    9090    /** Overlapped structure. */
    9191    OVERLAPPED            Overlapped;
     92    /** Current state the request is in. */
     93    RTFILEAIOREQSTATE     enmState;
    9294    /** The file handle. */
    9395    HANDLE                hFile;
     
    122124#define OVERLAPPED_2_RTFILEAIOREQINTERNAL(pOverlapped) ( (PRTFILEAIOREQINTERNAL)((uintptr_t)(pOverlapped) - RT_OFFSETOF(RTFILEAIOREQINTERNAL, Overlapped)) )
    123125
     126RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits)
     127{
     128    int rcBSD = 0;
     129    AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER);
     130
     131    /* No limits known. */
     132    pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS;
     133    pAioLimits->cbBufferAlignment   = 0;
     134
     135    return VINF_SUCCESS;
     136}
     137
    124138RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq)
    125139{
     
    133147    pReqInt->fCompleted = false;
    134148    pReqInt->u32Magic   = RTFILEAIOREQ_MAGIC;
     149    RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    135150
    136151    *phReq = (RTFILEAIOREQ)pReqInt;
     
    139154}
    140155
    141 RTDECL(void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
     156RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
    142157{
    143158    /*
     
    145160     */
    146161    if (hReq == NIL_RTFILEAIOREQ)
    147         return;
     162        return VINF_SUCCESS;
    148163    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    149     RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt);
     164    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     165    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    150166
    151167    /*
     
    154170    ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC);
    155171    RTMemFree(pReqInt);
     172    return VINF_SUCCESS;
    156173}
    157174
     
    169186    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    170187    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     188    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    171189    Assert(hFile != NIL_RTFILE);
    172190    AssertPtr(pvBuf);
     
    204222    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    205223    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     224    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    206225    AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
    207226
     
    226245    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    227246    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     247    RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);
    228248
    229249    /**
     
    234254     * is only available from Vista and up.
    235255     * The solution is to return VERR_FILE_AIO_IN_PROGRESS
    236      * if the request didn't completed yet.
     256     * if the request didn't completed yet (checked above).
    237257     * Shouldn't be a big issue because a request is normally
    238258     * only canceled if it exceeds a timeout which is quite huge.
    239259     */
    240     if (pReqInt->fCompleted)
    241         return VERR_FILE_AIO_COMPLETED;
    242     else
    243         return VERR_FILE_AIO_IN_PROGRESS;
     260    return VERR_FILE_AIO_COMPLETED;
    244261}
    245262
     
    249266    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    250267    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    251 
    252     if (pReqInt->fCompleted)
    253     {
    254         rc = pReqInt->Rc;
    255         if (*pcbTransfered)
    256             *pcbTransfered = pReqInt->cbTransfered;
    257     }
    258     else
    259         rc = VERR_FILE_AIO_IN_PROGRESS;
     268    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
     269    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
     270
     271    rc = pReqInt->Rc;
     272    if (pcbTransfered && RT_SUCCESS(rc))
     273        *pcbTransfered = pReqInt->cbTransfered;
    260274
    261275    return rc;
     
    325339}
    326340
    327 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
     341RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
    328342{
    329343    /*
    330344     * Parameter validation.
    331345     */
    332     AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);
    333     *pcReqs = 0;
    334346    int rc = VINF_SUCCESS;
    335347    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
     
    361373        if (RT_UNLIKELY(!fSucceeded && GetLastError() != ERROR_IO_PENDING))
    362374        {
     375            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    363376            rc = RTErrConvertFromWin32(GetLastError());
     377            pReqInt->Rc = rc;
    364378            break;
    365379        }
     380        RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);
    366381    }
    367382
    368     *pcReqs = i;
    369383    ASMAtomicAddS32(&pCtxInt->cRequests, i);
    370384
     
    440454
    441455            /* Mark the request as finished. */
    442             pReqInt->fCompleted = true;
     456            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    443457
    444458            /* completion status. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette