VirtualBox

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


Ignore:
Timestamp:
May 5, 2009 12:20:09 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
46871
Message:

Runtime/Aio: Fix the POSIX backend for Darwin. We have to obey the AIO_LISTIO_MAX limit when calling lio_listio. Submitting more requests than AIO_LISTIO_MAX makes the call fail

File:
1 edited

Legend:

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

    r19348 r19370  
    4747#include <aio.h>
    4848#include <errno.h>
    49 
    50 #define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64
     49#include <time.h>
     50
     51/*
     52 * Linux does not define this value.
     53 * Just define it with really big
     54 * value.
     55 */
     56#ifndef AIO_LISTIO_MAX
     57# define AIO_LISTIO_MAX UINT32_MAX
     58#endif
    5159
    5260/*******************************************************************************
     
    417425}
    418426
    419 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ phReqs, size_t cReqs, size_t *pcReqs)
    420 {
     427RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
     428{
     429    int rc = VINF_SUCCESS;
    421430    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    422431
     
    424433    AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE);
    425434    AssertReturn(cReqs != 0, VERR_INVALID_POINTER);
    426     AssertPtrReturn(phReqs,  VERR_INVALID_PARAMETER);
     435    AssertPtrReturn(pahReqs,  VERR_INVALID_PARAMETER);
    427436
    428437    /* Check that we don't exceed the limit */
     
    431440
    432441    PRTFILEAIOREQINTERNAL pHead = NULL;
    433     for (size_t i = 0; i < cReqs; i++)
    434     {
    435         PRTFILEAIOREQINTERNAL pReqInt = phReqs[i];
    436 
    437         pReqInt->pCtxInt = pCtxInt;
    438         /* Link them together. */
    439         pReqInt->pNext = pHead;
    440         pHead = pReqInt;
    441     }
    442 
    443     int rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)phReqs, cReqs, NULL);
    444     if (RT_UNLIKELY(rcPosix < 0))
    445         return RTErrConvertFromErrno(errno);
    446 
    447     ASMAtomicAddS32(&pCtxInt->cRequests, cReqs);
    448     *pcReqs = cReqs;
    449 
    450     /*
    451      * Forward them to the thread waiting for requests.
    452      * We search for a free slot first and if we don't find one
    453      * we will grab the first one and append our list to the existing entries.
    454      */
    455     unsigned iSlot = 0;
    456     while (  (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead))
    457            && !ASMAtomicCmpXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[iSlot], pHead, NULL))
    458         iSlot++;
    459 
    460     if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead))
    461     {
    462         /* Nothing found. */
    463         PRTFILEAIOREQINTERNAL pOldHead = (PRTFILEAIOREQINTERNAL)ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0],
    464                                                                                   NULL);
    465 
    466         /* Find the end of the current head and link the old list to the current. */
    467         PRTFILEAIOREQINTERNAL pTail = pHead;
    468         while (pTail->pNext)
    469             pTail = pTail->pNext;
    470 
    471         pTail->pNext = pOldHead;
    472 
    473         ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], pHead);
    474     }
    475 
    476     /* Set the internal wakeup flag and wakeup the thread if possible. */
    477     bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true);
    478     if (!fWokenUp)
    479         rtFileAioCtxWakeup(pCtxInt);
    480 
    481     return VINF_SUCCESS;
     442
     443    do
     444    {
     445        int rcPosix = 0;
     446        size_t cReqsSubmit = 0;
     447        size_t i = 0;
     448        PRTFILEAIOREQINTERNAL pReqInt;
     449
     450        while (   (i < cReqs)
     451               && (i < AIO_LISTIO_MAX))
     452        {
     453            pReqInt = pahReqs[i];
     454            RTFILEAIOREQ_VALID_RETURN(pReqInt);
     455
     456            pReqInt->pCtxInt = pCtxInt;
     457
     458            /* Link them together. */
     459            pReqInt->pNext = pHead;
     460            pHead = pReqInt;
     461
     462            if (pReqInt->fFlush)
     463                break;
     464
     465            cReqsSubmit++;
     466            i++;
     467        }
     468
     469        if (cReqsSubmit)
     470        {
     471            rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
     472            if (RT_UNLIKELY(rcPosix < 0))
     473            {
     474                rc = RTErrConvertFromErrno(errno);
     475                break;
     476            }
     477
     478            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
     479            cReqs   -= cReqsSubmit;
     480            pahReqs += cReqsSubmit;
     481            *pcReqs += cReqsSubmit;
     482        }
     483
     484        /* Check if we have a flush request now. */
     485        if (cReqs)
     486        {
     487            pReqInt = pahReqs[0];
     488            RTFILEAIOREQ_VALID_RETURN(pReqInt);
     489
     490            if (pReqInt->fFlush)
     491            {
     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++;
     507            }
     508        }
     509    } while (cReqs);
     510
     511    if (pHead)
     512    {
     513        /*
     514         * Forward successfully submitted requests to the thread waiting for requests.
     515         * We search for a free slot first and if we don't find one
     516         * we will grab the first one and append our list to the existing entries.
     517         */
     518        unsigned iSlot = 0;
     519        while (  (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead))
     520               && !ASMAtomicCmpXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[iSlot], pHead, NULL))
     521            iSlot++;
     522
     523        if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead))
     524        {
     525            /* Nothing found. */
     526            PRTFILEAIOREQINTERNAL pOldHead = (PRTFILEAIOREQINTERNAL)ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0],
     527                                                                                      NULL);
     528
     529            /* Find the end of the current head and link the old list to the current. */
     530            PRTFILEAIOREQINTERNAL pTail = pHead;
     531            while (pTail->pNext)
     532                pTail = pTail->pNext;
     533
     534            pTail->pNext = pOldHead;
     535
     536            ASMAtomicXchgPtr((void * volatile *)&pCtxInt->apReqsNewHead[0], pHead);
     537        }
     538
     539        /* Set the internal wakeup flag and wakeup the thread if possible. */
     540        bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true);
     541        if (!fWokenUp)
     542            rtFileAioCtxWakeup(pCtxInt);
     543    }
     544
     545    return rc;
    482546}
    483547
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