VirtualBox

Changeset 93631 in vbox


Ignore:
Timestamp:
Feb 7, 2022 12:45:08 AM (3 years ago)
Author:
vboxsync
Message:

VMM/PDMNetShaper: Don't start the unchoke thread unless there are are one or more bandwidth groups configured. Make the unchoke thread wait on an event sempahore so it can be woken up when needed and stop wasting cpu cycles and battery on lots of unnecessary wakups. Use a timer (real time clock) to wake up the unchoke timer when needed. bugref:10093 bugref:5582

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/PDMAllNetShaper.cpp

    r93628 r93631  
    6060                     * Re-fill the bucket first
    6161                     */
    62                     uint64_t const tsNow    = RTTimeSystemNanoTS();
    63                     uint64_t const cNsDelta = tsNow - pGroup->tsUpdatedLast;
     62                    uint64_t const nsNow    = RTTimeSystemNanoTS();
     63                    uint64_t const cNsDelta = nsNow - pGroup->tsUpdatedLast;
    6464                    /** @todo r=bird: there might be an overflow issue here if the gap
    6565                     *                between two transfers is too large. */
     
    7676                    {
    7777                        pGroup->cbTokensLast  = cTokens - (uint32_t)cbTransfer;
    78                         pGroup->tsUpdatedLast = tsNow;
     78                        pGroup->tsUpdatedLast = nsNow;
    7979                        Log2(("pdmNsAllocateBandwidth/%s: allowed - cbTransfer=%#zx cTokens=%#x cTokensAdded=%#x\n",
    8080                              pGroup->szName, cbTransfer, cTokens, cTokensAdded));
     
    8282                    else
    8383                    {
     84                        /*
     85                         * No, we're choked.  Arm the unchoke timer for the next period.
     86                         * Just do this on a simple PDM_NETSHAPER_MAX_LATENCY clock granularity.
     87                         * ASSUMES the timer uses millisecond resolution clock.
     88                         */
    8489                        ASMAtomicWriteBool(&pFilter->fChoked, true);
    85                         Log2(("pdmNsAllocateBandwidth/%s: refused - cbTransfer=%#zx cTokens=%#x cTokensAdded=%#x\n",
    86                               pGroup->szName, cbTransfer, cTokens, cTokensAdded));
     90                        if (ASMAtomicCmpXchgBool(&pVM->pdm.s.fNsUnchokeTimerArmed, true, false))
     91                        {
     92                            Assert(TMTimerGetFreq(pVM, pVM->pdm.s.hNsUnchokeTimer) == RT_MS_1SEC);
     93                            uint64_t const msNow    = TMTimerGet(pVM, pVM->pdm.s.hNsUnchokeTimer);
     94                            uint64_t const msExpire = (msNow / PDM_NETSHAPER_MAX_LATENCY + 1) * PDM_NETSHAPER_MAX_LATENCY;
     95                            rc = TMTimerSet(pVM, pVM->pdm.s.hNsUnchokeTimer, msExpire);
     96                            AssertRC(rc);
     97
     98                            Log2(("pdmNsAllocateBandwidth/%s: refused - cbTransfer=%#zx cTokens=%#x cTokensAdded=%#x cMsExpire=%u\n",
     99                                  pGroup->szName, cbTransfer, cTokens, cTokensAdded, msExpire - msNow));
     100                        }
     101                        else
     102                            Log2(("pdmNsAllocateBandwidth/%s: refused - cbTransfer=%#zx cTokens=%#x cTokensAdded=%#x\n",
     103                                  pGroup->szName, cbTransfer, cTokens, cTokensAdded));
    87104                        fAllowed = false;
    88105                    }
  • trunk/src/VBox/VMM/VMMR3/PDMNetShaper.cpp

    r93630 r93631  
    3030#include <iprt/asm.h>
    3131#include <iprt/assert.h>
     32#include <iprt/critsect.h>
     33#include <iprt/string.h>
     34#include <iprt/semaphore.h>
    3235#include <iprt/thread.h>
    33 #include <iprt/mem.h>
    34 #include <iprt/critsect.h>
    35 #include <iprt/tcp.h>
    36 #include <iprt/path.h>
    37 #include <iprt/string.h>
    3836
    3937#include <VBox/vmm/pdmnetshaper.h>
     
    203201
    204202/**
    205  * This is used both by pdmR3NsTxThread and PDMR3NsBwGroupSetLimit,
     203 * This is used both by pdmR3NsUnchokeThread and PDMR3NsBwGroupSetLimit,
    206204 * the latter only when setting cbPerSecMax to zero.
    207205 *
     
    316314
    317315/**
    318  * I/O thread for pending TX.
     316 * I/O thread for pending unchoking and associating transmitting.
    319317 *
    320318 * @returns VINF_SUCCESS (ignored).
     
    322320 * @param   pThread     The PDM thread data.
    323321 */
    324 static DECLCALLBACK(int) pdmR3NsTxThread(PVM pVM, PPDMTHREAD pThread)
    325 {
    326     LogFlow(("pdmR3NsTxThread: pVM=%p\n", pVM));
     322static DECLCALLBACK(int) pdmR3NsUnchokeThread(PVM pVM, PPDMTHREAD pThread)
     323{
     324    LogFlow(("pdmR3NsUnchokeThread: pVM=%p\n", pVM));
    327325    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    328326    {
    329         /** @todo r=bird: This sleep is horribly crude and wasteful! (Michael would go nuts if he knew) */
    330         RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY);
     327        int rc = RTSemEventWait(pVM->pdm.s.hNsUnchokeEvt, RT_INDEFINITE_WAIT);
     328        if (pThread->enmState != PDMTHREADSTATE_RUNNING)
     329            break;
     330        AssertMsgStmt(RT_SUCCESS(rc) || rc == VERR_TIMEOUT /* paranioa*/, ("%Rrc\n", rc),
     331                      RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY));
    331332
    332333        /*
     
    336337         * from taking place while we're traversing the filter lists.
    337338         */
    338         int rc = RTCritSectEnter(&pVM->pdm.s.NsLock);
     339        rc = RTCritSectEnter(&pVM->pdm.s.NsLock);
    339340        AssertRC(rc);
    340341
     
    358359 * @copydoc FNPDMTHREADWAKEUPINT
    359360 */
    360 static DECLCALLBACK(int) pdmR3NsTxWakeUp(PVM pVM, PPDMTHREAD pThread)
    361 {
    362     RT_NOREF2(pVM, pThread);
    363     LogFlow(("pdmR3NsTxWakeUp: pShaper=%p\n", pThread->pvUser));
    364     /* Nothing to do */
    365     /** @todo r=bird: use a semaphore, this'll cause a PDM_NETSHAPER_MAX_LATENCY/2
    366      *        delay every time we pause the VM! Stupid stupid stupid. */
     361static DECLCALLBACK(int) pdmR3NsUnchokeWakeUp(PVM pVM, PPDMTHREAD pThread)
     362{
     363    LogFlow(("pdmR3NsUnchokeWakeUp:\n"));
     364
     365    /* Wake up the thread. */
     366    int rc = RTSemEventSignal(pVM->pdm.s.hNsUnchokeEvt);
     367    AssertRC(rc);
     368
     369    RT_NOREF(pThread);
    367370    return VINF_SUCCESS;
     371}
     372
     373
     374/**
     375 * @callback_method_impl{FNTMTIMERINT, Wakes up pdmR3NsUnchokeThread.}
     376 */
     377static DECLCALLBACK(void) pdmR3NsUnchokeTimer(PVM pVM, TMTIMERHANDLE hTimer, void *pvUser)
     378{
     379    ASMAtomicWriteBool(&pVM->pdm.s.fNsUnchokeTimerArmed, false);
     380
     381    /* Wake up the thread. */
     382    int rc = RTSemEventSignal(pVM->pdm.s.hNsUnchokeEvt);
     383    AssertRC(rc);
     384
     385    RT_NOREF(hTimer, pvUser);
    368386}
    369387
     
    400418    LogFlow(("pdmR3NetShaperInit: pVM=%p\n", pVM));
    401419    VM_ASSERT_EMT(pVM);
     420
     421    Assert(pVM->pdm.s.cNsGroups == 0);
     422    pVM->pdm.s.hNsUnchokeEvt   = NIL_RTSEMEVENT;
     423    pVM->pdm.s.hNsUnchokeTimer = NIL_TMTIMERHANDLE;
    402424
    403425    /*
     
    467489    {
    468490        /*
    469          * Create the transmit thread.
     491         * If there are any groups configured, create a unchoke thread and an
     492         * associated timer for waking it up when needed.   The timer runs on
     493         * the real time clock.
    470494         */
    471         rc = PDMR3ThreadCreate(pVM, &pVM->pdm.s.pNsTxThread, NULL, pdmR3NsTxThread, pdmR3NsTxWakeUp,
    472                                0 /*cbStack*/, RTTHREADTYPE_IO, "PDMNsTx");
     495        if (pVM->pdm.s.cNsGroups == 0)
     496        {
     497            LogFlowFunc(("returns VINF_SUCCESS - no groups\n"));
     498            return VINF_SUCCESS;
     499        }
     500
     501        rc = RTSemEventCreate(&pVM->pdm.s.hNsUnchokeEvt);
    473502        if (RT_SUCCESS(rc))
    474503        {
    475             LogFlowFunc(("returns VINF_SUCCESS\n"));
    476             return VINF_SUCCESS;
     504            rc = TMR3TimerCreate(pVM, TMCLOCK_REAL, pdmR3NsUnchokeTimer, NULL, TMTIMER_FLAGS_NO_RING0,
     505                                 "PDMNetShaperUnchoke", &pVM->pdm.s.hNsUnchokeTimer);
     506            if (RT_SUCCESS(rc))
     507            {
     508                rc = PDMR3ThreadCreate(pVM, &pVM->pdm.s.pNsUnchokeThread, NULL, pdmR3NsUnchokeThread, pdmR3NsUnchokeWakeUp,
     509                                       0 /*cbStack*/, RTTHREADTYPE_IO, "PDMNsUnchoke");
     510                if (RT_SUCCESS(rc))
     511                {
     512
     513                    LogFlowFunc(("returns VINF_SUCCESS (%u groups)\n", pVM->pdm.s.cNsGroups));
     514                    return VINF_SUCCESS;
     515                }
     516            }
    477517        }
    478518    }
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r93628 r93631  
    15141514    bool                            fStateLoaded;
    15151515    /** Alignment padding. */
    1516     bool                            afPadding[3];
     1516    bool                            afPadding1[3];
    15171517
    15181518    /** The tracing ID of the next device instance.
     
    15441544    /** @name Network Shaper
    15451545     * @{ */
    1546     /** Pending TX thread. */
    1547     PPDMTHREAD                      pNsTxThread;
    1548     uint32_t                        au32Padding[1+8];
     1546    /** Thread that processes choked filter drivers after
     1547     * the a PDM_NETSHAPER_MAX_LATENCY period has elapsed. */
     1548    PPDMTHREAD                      pNsUnchokeThread;
     1549    /** Semaphore that the TX thread waits on. */
     1550    RTSEMEVENT                      hNsUnchokeEvt;
     1551    /** Timer handle for waking up pNsUnchokeThread. */
     1552    TMTIMERHANDLE                   hNsUnchokeTimer;
     1553    /** Indicates whether the unchoke timer has been armed already or not. */
     1554    bool volatile                   fNsUnchokeTimerArmed;
     1555    /** Align aNsGroups on a cacheline.   */
     1556    bool                            afPadding2[19];
    15491557    /** Number of network shaper groups.
    15501558     * @note Marked volatile to prevent re-reading after validation. */
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