VirtualBox

Changeset 19185 in vbox


Ignore:
Timestamp:
Apr 26, 2009 9:04:33 AM (16 years ago)
Author:
vboxsync
Message:

Runtime/Aio: Slight changes to the API for Windows. Fix the Solaris backend

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/file.h

    r19125 r19185  
    787787 * RTFileAioReqPrepareWrite() which will write to a given file.
    788788 *
    789  * The second object is the context. Requests are associated with a context
    790  * during RTFileAioCtxSubmit() which will also submit the requests to the
    791  * operating system.
     789 * The second object is the context. A file is associated with a context
     790 * and requests for this file may complete only on the context the file
     791 * was associated with and not on the context given in RTFileAioCtxSubmit()
     792 * (see below for further information).
    792793 * RTFileAioCtxWait() is used to wait for completion of requests which were
    793794 * associated with the context. While waiting for requests the thread can not
     
    811812 * there are some things to consider to make the code as portable as possible.
    812813 *
    813  * The only restriction at the moment is that every buffer has to be aligned to a 512 byte boundary.
     814 * The first restriction at the moment is that every buffer has to be aligned to a 512 byte boundary.
    814815 * This limitation comes from the Linux io_* interface. To use the interface the file
    815816 * must be opened with O_DIRECT. This flag disables the kernel cache too which may
     
    822823 * file systems. So Linus comment about this flag is comprehensible but Linux
    823824 * lacks an alternative at the moment.
     825 *
     826 * The next limitation applies only to Windows. Reqeusts are not assoicated with the
     827 * I/O context they are associated with but with the file the request is for.
     828 * The file needs to be associated with exactly one I/O completion port and requests
     829 * for this file will only arrive at that context after they completed and not on
     830 * the context the request was submitted.
     831 * To associate a file with a specific context RTFileAioCtxAssociateWithFile() is
     832 * used. It is only implemented on Windows and does nothing on the other platforms.
     833 * If the file needs to be associated with different context for some reason
     834 * the file must be closed first. After it was opened again the new context
     835 * can be associated with the other context.
     836 * This can't be done by the API because there is no way to retrieve the flags
     837 * the file was opened with.
    824838 */
    825839
     
    963977
    964978/**
     979 * Associates a file with a async I/O context.
     980 * Requests for this file will arrive at the completion port
     981 * associated with the file.
     982 *
     983 * @returns IPRT status code.
     984 *
     985 * @param   hAioCtx        The async I/O context handle.
     986 * @param   hFile          The file handle.
     987 */
     988RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile);
     989
     990/**
    965991 * Submits a set of requests to an async I/O context for processing.
    966  *
    967  * @todo Is it possible to call this API while another thread is in
    968  *       RTFileAioCtxWait?
    969992 *
    970993 * @returns IPRT status code.
     
    973996 * @param   pahReqs         Pointer to an array of request handles.
    974997 * @param   cReqs           The number of entries in the array.
     998 * @param   pcReqs          Where to store the number of requests
     999 *                          successfully submitted before an error
     1000 *                          occured. If VINF_SUCCESS is returned
     1001 *                          the value equals cReqs. This value is always
     1002 *                          set.
    9751003 *
    9761004 * @remarks @a cReqs uses the type size_t while it really is a uint32_t, this is
     
    9781006 *          macros.
    9791007 */
    980 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ phReqs, size_t cReqs);
     1008RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs);
    9811009
    9821010/**
  • trunk/src/VBox/Runtime/r3/linux/fileaio-linux.cpp

    r19126 r19185  
    458458        *phAioCtx = (RTFILEAIOCTX)pCtxInt;
    459459    }
     460    else
     461        RTMemFree(pCtxInt);
    460462
    461463    return rc;
     
    500502}
    501503
    502 
    503 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
     504RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTS hAioCtx, RTFILE hFile)
     505{
     506    /* Nothing to do. */
     507    return VINF_SUCCESS;
     508}
     509
     510RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
    504511{
    505512    /*
    506513     * Parameter validation.
    507514     */
     515    AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);
     516    *pcReqs = 0;
    508517    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    509518    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
     
    539548    if (RT_FAILURE(rc))
    540549        ASMAtomicSubS32(&pCtxInt->cRequests, cReqs);
     550    else
     551        *pcReqs = cReqs;
    541552
    542553    return rc;
  • trunk/src/VBox/Runtime/testcase/tstFileAio.cpp

    r19054 r19185  
    6363        RTFOFF           Offset = 0;
    6464        size_t           cbLeft = cbTestFile;
    65 
    66         /* Initialize buffers. */
    67         for (unsigned i = 0; i < RT_ELEMENTS(apvBuf); i++)
     65        int cRun = 0;
     66
     67        /* Associate file with context.*/
     68        rc = RTFileAioCtxAssociateWithFile(hAioContext, File);
     69        if (RT_SUCCESS(rc))
    6870        {
    69             apvBuf[i] = RTMemPageAllocZ(cbTestBuf);
    70 
    71             if (fWrite)
    72                 memcpy(apvBuf[i], pvTestBuf, cbTestBuf);
     71            /* Initialize buffers. */
     72            for (unsigned i = 0; i < RT_ELEMENTS(apvBuf); i++)
     73            {
     74                apvBuf[i] = RTMemPageAllocZ(cbTestBuf);
     75
     76                if (fWrite)
     77                    memcpy(apvBuf[i], pvTestBuf, cbTestBuf);
     78            }
     79
     80            /* Initialize requests. */
     81            for (unsigned i = 0; i < RT_ELEMENTS(aReqs); i++)
     82                RTFileAioReqCreate(&aReqs[i]);
     83
     84            while (cbLeft)
     85            {
     86                int cReqs = 0;
     87                size_t cReqsSubmitted = 0;
     88
     89                for (unsigned i = 0; i < RT_ELEMENTS(aReqs); i++)
     90                {
     91                    size_t cbTransfer = (cbLeft < cbTestBuf) ? cbLeft : cbTestBuf;
     92
     93                    if (!cbTransfer)
     94                        break;
     95
     96                    if (fWrite)
     97                        rc = RTFileAioReqPrepareWrite(aReqs[i], File, Offset, apvBuf[i],
     98                                                      cbTransfer, apvBuf[i]);
     99                    else
     100                        rc = RTFileAioReqPrepareRead(aReqs[i], File, Offset, apvBuf[i],
     101                                                     cbTransfer, apvBuf[i]);
     102
     103                    cbLeft -= cbTransfer;
     104                    Offset += cbTransfer;
     105                    cReqs++;
     106                }
     107
     108                rc = RTFileAioCtxSubmit(hAioContext, aReqs, cReqs, &cReqsSubmitted);
     109                if (RT_FAILURE(rc))
     110                {
     111                    RTPrintf("tstFileAio: FATAL ERROR - Failed to submit tasks after %d runs. rc=%Rrc\n", cRun, rc);
     112                    cErrors++;
     113                    break;
     114                }
     115                else if (cReqs != cReqsSubmitted)
     116                {
     117                    RTPrintf("tstFileAio: FATAL ERROR - Submitted tasks but the result is not equal to the number of submitted tasks\n", rc);
     118                    cErrors++;
     119                    break;
     120                }
     121
     122                /* Wait */
     123                RTFILEAIOREQ aReqsCompleted[TSTFILEAIO_MAX_REQS_IN_FLIGHT];
     124                uint32_t cCompleted = 0;
     125                rc = RTFileAioCtxWait(hAioContext, cReqs, RT_INDEFINITE_WAIT,
     126                                      aReqsCompleted, TSTFILEAIO_MAX_REQS_IN_FLIGHT,
     127                                      &cCompleted);
     128                if (RT_FAILURE(rc))
     129                {
     130                    RTPrintf("tstFileAio: FATAL ERROR - Waiting failed. rc=%Rrc\n", rc);
     131                    cErrors++;
     132                    break;
     133                }
     134
     135                if (!fWrite)
     136                {
     137                    for (uint32_t i = 0; i < cCompleted; i++)
     138                    {
     139                        /* Compare that we read the right stuff. */
     140                        void *pvBuf = RTFileAioReqGetUser(aReqsCompleted[i]);
     141
     142                        size_t cbTransfered;
     143                        int rcReq = RTFileAioReqGetRC(aReqsCompleted[i], &cbTransfered);
     144                        if (RT_FAILURE(rcReq) || (cbTransfered != cbTestBuf))
     145                        {
     146                            RTPrintf("tstFileAio: FATAL ERROR - Request %d failed with rc=%Rrc cbTransfered=%d.\n",
     147                                     i, rcReq, cbTransfered);
     148                            cErrors++;
     149                            rc = rcReq;
     150                            break;
     151                        }
     152
     153                        if (memcmp(pvBuf, pvTestBuf, cbTestBuf) != 0)
     154                        {
     155                            RTPrintf("tstFileAio: FATAL ERROR - Unexpected content in memory.\n");
     156                            cErrors++;
     157                            break;
     158                        }
     159                        memset(pvBuf, 0, cbTestBuf);
     160                    }
     161                }
     162                cRun++;
     163                if (RT_FAILURE(rc))
     164                    break;
     165            }
     166
     167            /* Free buffers. */
     168            for (unsigned i = 0; i < RT_ELEMENTS(apvBuf); i++)
     169                RTMemPageFree(apvBuf[i]);
     170
     171            /* Free requests. */
     172            for (unsigned i = 0; i < RT_ELEMENTS(aReqs); i++)
     173                RTFileAioReqDestroy(aReqs[i]);
     174
     175            NanoTS = RTTimeNanoTS() - NanoTS;
     176            unsigned SpeedKBs = cbTestFile / (NanoTS / 1000000000.0) / 1024;
     177
     178            RTPrintf("tstFileAio: Completed simple %s test: %d.%03d MB/sec\n",
     179                     fWrite ? "write" : "read",
     180                     SpeedKBs / 1000,
     181                     SpeedKBs % 1000);
    73182        }
    74 
    75         /* Initialize requests. */
    76         for (unsigned i = 0; i < RT_ELEMENTS(aReqs); i++)
    77             RTFileAioReqCreate(&aReqs[i]);
    78 
    79         while (cbLeft)
     183        else
    80184        {
    81             int cReqs = 0;
    82 
    83             for (unsigned i = 0; i < RT_ELEMENTS(aReqs); i++)
    84             {
    85                 size_t cbTransfer = (cbLeft < cbTestBuf) ? cbLeft : cbTestBuf;
    86 
    87                 if (!cbTransfer)
    88                     break;
    89 
    90                 if (fWrite)
    91                     rc = RTFileAioReqPrepareWrite(aReqs[i], File, Offset, apvBuf[i],
    92                                                   cbTransfer, apvBuf[i]);
    93                 else
    94                     rc = RTFileAioReqPrepareRead(aReqs[i], File, Offset, apvBuf[i],
    95                                                  cbTransfer, apvBuf[i]);
    96 
    97                 cbLeft -= cbTransfer;
    98                 Offset += cbTransfer;
    99                 cReqs++;
    100             }
    101 
    102             rc = RTFileAioCtxSubmit(hAioContext, aReqs, cReqs);
    103             if (RT_FAILURE(rc))
    104             {
    105                 RTPrintf("tstFileAio: FATAL ERROR - Failed to submit tasks. rc=%Rrc\n", rc);
    106                 cErrors++;
    107                 break;
    108             }
    109 
    110             /* Wait */
    111             RTFILEAIOREQ aReqsCompleted[TSTFILEAIO_MAX_REQS_IN_FLIGHT];
    112             uint32_t cCompleted = 0;
    113             rc = RTFileAioCtxWait(hAioContext, cReqs, RT_INDEFINITE_WAIT,
    114                                   aReqsCompleted, TSTFILEAIO_MAX_REQS_IN_FLIGHT,
    115                                   &cCompleted);
    116             if (RT_FAILURE(rc))
    117             {
    118                 RTPrintf("tstFileAio: FATAL ERROR - Waiting failed. rc=%Rrc\n", rc);
    119                 cErrors++;
    120                 break;
    121             }
    122 
    123             if (!fWrite)
    124             {
    125                 for (uint32_t i = 0; i < cCompleted; i++)
    126                 {
    127                     /* Compare that we read the right stuff. */
    128                     void *pvBuf = RTFileAioReqGetUser(aReqsCompleted[i]);
    129 
    130                     if (memcmp(pvBuf, pvTestBuf, cbTestBuf) != 0)
    131                     {
    132                         RTPrintf("tstFileAio: FATAL ERROR - Unexpected content in memory.\n");
    133                         cErrors++;
    134                         break;
    135                     }
    136                     memset(pvBuf, 0, cbTestBuf);
    137                 }
    138             }
     185            RTPrintf("tstFileAio: FATAL ERROR - Failed to asssociate file with async I/O context. rc=%Rrc\n", rc);
     186            cErrors++;
    139187        }
    140 
    141         /* Free buffers. */
    142         for (unsigned i = 0; i < RT_ELEMENTS(apvBuf); i++)
    143             RTMemPageFree(apvBuf[i]);
    144 
    145         /* Free requests. */
    146         for (unsigned i = 0; i < RT_ELEMENTS(aReqs); i++)
    147             RTFileAioReqDestroy(aReqs[i]);
    148 
    149         NanoTS = RTTimeNanoTS() - NanoTS;
    150         unsigned SpeedKBs = cbTestFile / (NanoTS / 1000000000.0) / 1024;
    151 
    152         RTPrintf("tstFileAio: Completed simple %s test: %d.%03d MB/sec\n",
    153                  fWrite ? "write" : "read",
    154                  SpeedKBs / 1000,
    155                  SpeedKBs % 1000);
    156188
    157189        rc = RTFileAioCtxDestroy(hAioContext);
     
    190222    RTPrintf("tstFileAio: Preparing test file, this can take some time and needs quite a bit of harddisk\n");
    191223    tstFileAioTestReadWriteBasic(File, true, pvTestBuf, 64*_1K, 100*_1M);
    192     tstFileAioTestReadWriteBasic(File, false, pvTestBuf, 64*_1K, 100*_1M);
    193 
     224    /* Reopen the file. */
    194225    RTFileClose(File);
     226    rc = RTFileOpen(&File, "tstFileAio#1.tst", RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_ASYNC_IO);
     227    if (RT_SUCCESS(rc))
     228    {
     229        tstFileAioTestReadWriteBasic(File, false, pvTestBuf, 64*_1K, 100*_1M);
     230        RTFileClose(File);
     231    }
     232    else
     233    {
     234        RTPrintf("tstFileAio: FATAL ERROR - Failed to open file #1. rc=%Rrc\n", rc);
     235        cErrors++;
     236    }
     237
     238    /* Cleanup */
    195239    RTMemFree(pvTestBuf);
    196240    RTFileDelete("tstFileAio#1.tst");
Note: See TracChangeset for help on using the changeset viewer.

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