VirtualBox

Changeset 35205 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Dec 16, 2010 6:35:02 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
69045
Message:

AsyncCompletion: Don't waste CPU cycles when all endpoints have reached the bandwidth limit and go to sleep

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h

    r34432 r35205  
    167167    /** Size of the array. */
    168168    unsigned                               cReqEntries;
    169     /** Flag whether at least one endpoint reached its bandwidth limit. */
    170     bool                                   fBwLimitReached;
    171169    /** Memory cache for file range locks. */
    172170    RTMEMCACHE                             hMemCacheRangeLocks;
     171    /** Number of milliseconds to wait until the bandwidth is refreshed for at least
     172     * one endpoint and it is possible to process more requests. */
     173    RTMSINTERVAL                           msBwLimitExpired;
    173174    /** Critical section protecting the blocking event handling. */
    174175    RTCRITSECT                             CritSectBlockingEvent;
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp

    r34929 r35205  
    5959    {
    6060        /* Initialize request handle array. */
    61         pAioMgr->iFreeEntry = 0;
    62         pAioMgr->cReqEntries    = pAioMgr->cRequestsActiveMax;
    63         pAioMgr->pahReqsFree    = (RTFILEAIOREQ *)RTMemAllocZ(pAioMgr->cReqEntries * sizeof(RTFILEAIOREQ));
     61        pAioMgr->iFreeEntry       = 0;
     62        pAioMgr->cReqEntries      = pAioMgr->cRequestsActiveMax;
     63        pAioMgr->pahReqsFree      = (RTFILEAIOREQ *)RTMemAllocZ(pAioMgr->cReqEntries * sizeof(RTFILEAIOREQ));
     64        pAioMgr->msBwLimitExpired = RT_INDEFINITE_WAIT;
    6465
    6566        if (pAioMgr->pahReqsFree)
     
    979980        if (!pdmacEpIsTransferAllowed(&pEndpoint->Core, (uint32_t)pCurr->DataSeg.cbSeg, &msWhenNext))
    980981        {
    981             pAioMgr->fBwLimitReached = true;
     982            pAioMgr->msBwLimitExpired = RT_MIN(pAioMgr->msBwLimitExpired, msWhenNext);
    982983            break;
    983984        }
     
    10901091
    10911092        if (RT_UNLIKELY(   pAioMgr->cRequestsActiveMax == pAioMgr->cRequestsActive
    1092                         && !pEndpoint->pFlushReq
    1093                         && !pAioMgr->fBwLimitReached))
     1093                        && !pEndpoint->pFlushReq))
    10941094        {
    10951095#if 0
     
    12731273    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint = pAioMgr->pEndpointsHead;
    12741274
    1275     pAioMgr->fBwLimitReached = false;
     1275    pAioMgr->msBwLimitExpired = RT_INDEFINITE_WAIT;
    12761276
    12771277    while (pEndpoint)
     
    16041604            ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, true);
    16051605            if (!ASMAtomicReadBool(&pAioMgr->fWokenUp))
    1606                 rc = RTSemEventWait(pAioMgr->EventSem, RT_INDEFINITE_WAIT);
     1606                rc = RTSemEventWait(pAioMgr->EventSem, pAioMgr->msBwLimitExpired);
    16071607            ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, false);
    1608             AssertRC(rc);
     1608            Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
    16091609
    16101610            LogFlow(("Got woken up\n"));
     
    16261626            CHECK_RC(pAioMgr, rc);
    16271627
    1628             while (   pAioMgr->cRequestsActive
    1629                    || pAioMgr->fBwLimitReached)
    1630             {
    1631                 if (pAioMgr->cRequestsActive)
    1632                 {
    1633                     RTFILEAIOREQ  apReqs[20];
    1634                     uint32_t cReqsCompleted = 0;
    1635                     size_t cReqsWait;
    1636 
    1637                     if (pAioMgr->cRequestsActive > RT_ELEMENTS(apReqs))
    1638                         cReqsWait = RT_ELEMENTS(apReqs);
    1639                     else
    1640                         cReqsWait = pAioMgr->cRequestsActive;
    1641 
    1642                     LogFlow(("Waiting for %d of %d tasks to complete\n", 1, cReqsWait));
    1643 
    1644                     rc = RTFileAioCtxWait(pAioMgr->hAioCtx,
    1645                                           1,
    1646                                           RT_INDEFINITE_WAIT, apReqs,
    1647                                           cReqsWait, &cReqsCompleted);
    1648                     if (RT_FAILURE(rc) && (rc != VERR_INTERRUPTED))
    1649                         CHECK_RC(pAioMgr, rc);
    1650 
    1651                     LogFlow(("%d tasks completed\n", cReqsCompleted));
    1652 
    1653                     for (uint32_t i = 0; i < cReqsCompleted; i++)
    1654                         pdmacFileAioMgrNormalReqComplete(pAioMgr, apReqs[i]);
    1655 
    1656                     /* Check for an external blocking event before we go to sleep again. */
    1657                     if (pAioMgr->fBlockingEventPending)
     1628            while (pAioMgr->cRequestsActive)
     1629            {
     1630                RTFILEAIOREQ apReqs[20];
     1631                uint32_t     cReqsCompleted = 0;
     1632                size_t       cReqsWait;
     1633
     1634                if (pAioMgr->cRequestsActive > RT_ELEMENTS(apReqs))
     1635                    cReqsWait = RT_ELEMENTS(apReqs);
     1636                else
     1637                    cReqsWait = pAioMgr->cRequestsActive;
     1638
     1639                LogFlow(("Waiting for %d of %d tasks to complete\n", 1, cReqsWait));
     1640
     1641                rc = RTFileAioCtxWait(pAioMgr->hAioCtx,
     1642                                      1,
     1643                                      RT_INDEFINITE_WAIT, apReqs,
     1644                                      cReqsWait, &cReqsCompleted);
     1645                if (RT_FAILURE(rc) && (rc != VERR_INTERRUPTED))
     1646                    CHECK_RC(pAioMgr, rc);
     1647
     1648                LogFlow(("%d tasks completed\n", cReqsCompleted));
     1649
     1650                for (uint32_t i = 0; i < cReqsCompleted; i++)
     1651                    pdmacFileAioMgrNormalReqComplete(pAioMgr, apReqs[i]);
     1652
     1653                /* Check for an external blocking event before we go to sleep again. */
     1654                if (pAioMgr->fBlockingEventPending)
     1655                {
     1656                    rc = pdmacFileAioMgrNormalProcessBlockingEvent(pAioMgr);
     1657                    CHECK_RC(pAioMgr, rc);
     1658                }
     1659
     1660                /* Update load statistics. */
     1661                uint64_t uMillisCurr = RTTimeMilliTS();
     1662                if (uMillisCurr > uMillisEnd)
     1663                {
     1664                    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointCurr = pAioMgr->pEndpointsHead;
     1665
     1666                    /* Calculate timespan. */
     1667                    uMillisCurr -= uMillisEnd;
     1668
     1669                    while (pEndpointCurr)
    16581670                    {
    1659                         rc = pdmacFileAioMgrNormalProcessBlockingEvent(pAioMgr);
    1660                         CHECK_RC(pAioMgr, rc);
     1671                        pEndpointCurr->AioMgr.cReqsPerSec    = pEndpointCurr->AioMgr.cReqsProcessed / (uMillisCurr + PDMACEPFILEMGR_LOAD_UPDATE_PERIOD);
     1672                        pEndpointCurr->AioMgr.cReqsProcessed = 0;
     1673                        pEndpointCurr = pEndpointCurr->AioMgr.pEndpointNext;
    16611674                    }
    16621675
    1663                     /* Update load statistics. */
    1664                     uint64_t uMillisCurr = RTTimeMilliTS();
    1665                     if (uMillisCurr > uMillisEnd)
    1666                     {
    1667                         PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointCurr = pAioMgr->pEndpointsHead;
    1668 
    1669                         /* Calculate timespan. */
    1670                         uMillisCurr -= uMillisEnd;
    1671 
    1672                         while (pEndpointCurr)
    1673                         {
    1674                             pEndpointCurr->AioMgr.cReqsPerSec    = pEndpointCurr->AioMgr.cReqsProcessed / (uMillisCurr + PDMACEPFILEMGR_LOAD_UPDATE_PERIOD);
    1675                             pEndpointCurr->AioMgr.cReqsProcessed = 0;
    1676                             pEndpointCurr = pEndpointCurr->AioMgr.pEndpointNext;
    1677                         }
    1678 
    1679                         /* Set new update interval */
    1680                         uMillisEnd = RTTimeMilliTS() + PDMACEPFILEMGR_LOAD_UPDATE_PERIOD;
    1681                     }
    1682                 }
    1683                 else
    1684                 {
    1685                     /*
    1686                      * Bandwidth limit reached for all endpoints.
    1687                      * Yield and wait until we have enough resources again.
    1688                      */
    1689                     RTThreadYield();
     1676                    /* Set new update interval */
     1677                    uMillisEnd = RTTimeMilliTS() + PDMACEPFILEMGR_LOAD_UPDATE_PERIOD;
    16901678                }
    16911679
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