VirtualBox

Changeset 98095 in vbox


Ignore:
Timestamp:
Jan 16, 2023 3:17:49 PM (23 months ago)
Author:
vboxsync
Message:

Main/Console: Implemented a LED query optimization, where also keep track of LEDs on a per-type. This will prevent scanning all the sets and also skip any DeviceType_Null entries. bugref:9892

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r98091 r98095  
    810810    typedef struct LEDSET *PLEDSET;
    811811    PPDMLED volatile *i_getLedSet(uint32_t iLedSet);
     812    void i_setLedType(DeviceType_T *penmSubTypeEntry, DeviceType_T enmNewType);
     813    HRESULT i_refreshLedTypeArrays(AutoReadLock *pReadLock);
    812814    uint32_t i_allocateDriverLeds(uint32_t cLeds, uint32_t fTypes, DeviceType_T **ppSubTypes);
    813     void i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType);
     815    void i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType, uint32_t cLeds = 1);
    814816    void i_attachStatusDriver(PCFGMNODE pCtlInst, uint32_t fTypes, uint32_t cLeds, DeviceType_T **ppaSubTypes,
    815817                              Console::MediumAttachmentMap *pmapMediumAttachments,
     
    10681070    /** @name LEDs and their management
    10691071     * @{ */
    1070     /** Read/write lock separating LED allocations (write) from queries (read). */
     1072    /** Read/write lock separating LED allocations and per-type data construction
     1073     * (write) from queries (read). */
    10711074    RWLockHandle            mLedLock;
     1075    /** LED configuration generation.  This is increased whenever a new set is
     1076     *  allocated or a sub-device type changes. */
     1077    uint32_t                muLedGen;
     1078    /** The LED configuration generation which maLedTypes was constructed for. */
     1079    uint32_t                muLedTypeGen;
    10721080    /** Number of LED sets in use in maLedSets. */
    10731081    uint32_t                mcLedSets;
     
    10851093        DeviceType_T       *paSubTypes;
    10861094    } maLedSets[32];
     1095    /** LEDs data organized by DeviceType_T.
     1096     * This is reconstructed by Console::i_refreshLedTypeArrays() when
     1097     * Console::getDeviceActivity is called and mLedTypeGen doesn't match
     1098     * muLedGen. */
     1099    struct
     1100    {
     1101        /** Number of possibly valid entries in pappLeds. */
     1102        uint32_t            cLeds;
     1103        /** Number of allocated entries. */
     1104        uint32_t            cAllocated;
     1105        /** Array of pointer to LEDSET::papLed entries.
     1106         * The indirection is due to Console::i_drvStatus_UnitChanged() only knowing
     1107         * about the LEDSET::papLeds. */
     1108        PPDMLED volatile  **pappLeds;
     1109    } maLedTypes[DeviceType_End];
    10871110    /** @} */
    10881111
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r98091 r98095  
    428428    , mBusMgr(NULL)
    429429    , mLedLock(LOCKCLASS_LISTOFOTHEROBJECTS /* must be higher than LOCKCLASS_OTHEROBJECT */)
     430    , muLedGen(0)
     431    , muLedTypeGen(0)
     432    , mcLedSets(0)
    430433    , m_pKeyStore(NULL)
    431434    , mpIfSecKey(NULL)
     
    438441    , mpCryptoIf(NULL)
    439442{
     443    RT_ZERO(maLedSets);
     444    RT_ZERO(maLedTypes);
    440445}
    441446
     
    446451{
    447452    LogFlowThisFunc(("\n"));
    448 
    449     mcLedSets = 0;
    450     RT_ZERO(maLedSets);
    451453
    452454    MYVMM2USERMETHODS *pVmm2UserMethods = (MYVMM2USERMETHODS *)RTMemAllocZ(sizeof(*mpVmm2UserMethods) + sizeof(Console *));
     
    881883
    882884    /* Release memory held by the LED sets (no need to take lock). */
     885    for (size_t idxType = 0; idxType < RT_ELEMENTS(maLedTypes); idxType++)
     886    {
     887        maLedTypes[idxType].cLeds = 0;
     888        maLedTypes[idxType].cAllocated = 0;
     889        RTMemFree(maLedTypes[idxType].pappLeds);
     890        maLedTypes[idxType].pappLeds = NULL;
     891    }
    883892    for (size_t idxSet = 0; idxSet < mcLedSets; idxSet++)
    884893    {
     894        maLedSets[idxSet].cLeds = 0;
    885895        RTMemFree((void *)maLedSets[idxSet].papLeds);
    886896        maLedSets[idxSet].papLeds = NULL;
     
    28152825}
    28162826
     2827/**
     2828 * Refreshes the maLedTypes and muLedTypeGen members.
     2829 */
     2830HRESULT Console::i_refreshLedTypeArrays(AutoReadLock *pReadLock)
     2831{
     2832    pReadLock->release();
     2833    AutoWriteLock alock(mLedLock COMMA_LOCKVAL_SRC_POS);
     2834
     2835    /*
     2836     * Check that the refresh was already done by someone else while we
     2837     * acquired the write lock.
     2838     */
     2839    if (muLedTypeGen != muLedGen)
     2840    {
     2841        /*
     2842         * Reset the data.
     2843         */
     2844        for (size_t idxType = 0; idxType < RT_ELEMENTS(maLedTypes); idxType++)
     2845            maLedTypes[idxType].cLeds = 0;
     2846
     2847        /*
     2848         * Rebuild the data.
     2849         */
     2850        for (uint32_t idxSet = 0; idxSet < mcLedSets; idxSet++)
     2851        {
     2852            PLEDSET const            pLS        = &maLedSets[idxSet];
     2853            uint32_t const           cLeds      = pLS->cLeds;
     2854            PPDMLED volatile * const papSrcLeds = pLS->papLeds;
     2855            DeviceType_T * const     paSubTypes = pLS->paSubTypes;
     2856            for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++)
     2857            {
     2858                /** @todo If we make Console::i_drvStatus_UnitChanged() modify the generation
     2859                 * too, we could skip NULL entries here and make it a bit more compact.
     2860                 * OTOH, most unused LED entires have a paSubTypes of DeviceType_Null. */
     2861                DeviceType_T enmType = paSubTypes ? paSubTypes[idxLed] : (DeviceType_T)(ASMBitFirstSetU32(pLS->fTypes) - 1);
     2862                if (enmType > DeviceType_Null && enmType < DeviceType_End)
     2863                {
     2864                    uint32_t const idxLedType = maLedTypes[enmType].cLeds;
     2865                    if (idxLedType >= maLedTypes[enmType].cAllocated)
     2866                    {
     2867                        void *pvNew = RTMemRealloc(maLedTypes[enmType].pappLeds,
     2868                                                   sizeof(maLedTypes[0].pappLeds[0]) * (idxLedType + 16));
     2869                        if (!pvNew)
     2870                            return E_OUTOFMEMORY;
     2871                        maLedTypes[enmType].pappLeds   = (PPDMLED volatile  **)pvNew;
     2872                        maLedTypes[enmType].cAllocated = idxLedType + 16;
     2873                    }
     2874                    maLedTypes[enmType].pappLeds[idxLedType] = &papSrcLeds[idxLed];
     2875                    maLedTypes[enmType].cLeds                = idxLedType + 1;
     2876                }
     2877            }
     2878        }
     2879        muLedTypeGen = muLedGen;
     2880    }
     2881
     2882    /*
     2883     * We have to release the write lock before re-acquiring the read-lock.
     2884     *
     2885     * This means there is a theoretical race here, however we ASSUME that
     2886     * LED sets are never removed and therefore we will be just fine
     2887     * accessing slightly dated per-type data.
     2888     */
     2889    alock.release();
     2890    pReadLock->acquire();
     2891    return S_OK;
     2892}
     2893
    28172894/** read the value of a LED. */
    28182895DECLINLINE(uint32_t) readAndClearLed(PPDMLED pLed)
     
    28282905{
    28292906    /*
    2830      * Make a roadmap of which DeviceType_T LED types are wanted:
     2907     * Make a roadmap of which DeviceType_T LED types are wanted.
     2908     *
     2909     * Note! This approach means we'll return the same values in aActivity for
     2910     *       duplicate aType entries.
    28312911     */
    2832     uint32_t fWanted = 0;
     2912    uint32_t fRequestedTypes = 0;
    28332913    AssertCompile(DeviceType_End <= 32);
    28342914
     
    28362916    {
    28372917        DeviceType_T const enmType = aType[iType];
     2918        AssertCompile((unsigned)DeviceType_Null == 0 /* first */);
    28382919        AssertReturn(enmType > DeviceType_Null && enmType < DeviceType_End,
    28392920                     setError(E_INVALIDARG, tr("Invalid DeviceType for getDeviceActivity in entry #%u: %d"), iType, enmType));
    2840         fWanted |= RT_BIT_32((unsigned)enmType);
    2841     }
    2842 
    2843     /* Resize the result vector before making changes (may throw, paranoia). */
     2921        fRequestedTypes |= RT_BIT_32((unsigned)enmType);
     2922    }
     2923
     2924    /*
     2925     * Resize the result vector before making changes (may throw, paranoia).
     2926     */
    28442927    aActivity.resize(aType.size());
    28452928
    28462929    /*
    2847      * Collect all the LEDs in a single sweep through all drivers' sets:
    2848      *
    2849      * Because this method can be called by the frontend and others while the
    2850      * VM is being constructed, we use a dedicated lock to prevent stumbling
    2851      * into the allocator.
     2930     * Accumulate the per-type data for all the requested types.
     2931     * We will lazily refresh the per-type data collection here when needed.
    28522932     */
    28532933    PDMLEDCORE aLEDs[DeviceType_End] = { {0} };
     
    28552935    {
    28562936        AutoReadLock alock(mLedLock COMMA_LOCKVAL_SRC_POS);
    2857         uint32_t idxSet = mcLedSets;
    2858         while (idxSet-- > 0)
    2859         {
    2860             /* Look inside this driver's set of LEDs and check if the types mask overlap with the request: */
    2861             PLEDSET pLS = &maLedSets[idxSet];
    2862             if (pLS->fTypes & fWanted)
     2937        if (RT_LIKELY(muLedGen == muLedTypeGen))
     2938        { /* likely */ }
     2939        else
     2940        {
     2941            HRESULT hrc = i_refreshLedTypeArrays(&alock);
     2942            if (FAILED(hrc))
     2943                return hrc;
     2944        }
     2945
     2946        AssertCompile((unsigned)DeviceType_Null == 0 /* we skip this one */);
     2947        for (uint32_t idxType = 1; idxType < RT_ELEMENTS(maLedTypes); idxType++)
     2948            if (fRequestedTypes & RT_BIT_32(idxType))
    28632949            {
    2864                 uint32_t const           cLeds      = pLS->cLeds;
    2865                 PPDMLED volatile * const papSrcLeds = pLS->papLeds;
    2866 
    2867                 /* Multi-type drivers (e.g. SCSI) have a subtype array which must be matched. */
    2868                 DeviceType_T const *paSubTypes = pLS->paSubTypes;
    2869                 if (paSubTypes)
    2870                     for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++)
    2871                     {
    2872                         DeviceType_T const enmType = paSubTypes[idxLed];
    2873                         Assert((unsigned)enmType < (unsigned)DeviceType_End);
    2874                         if (fWanted & RT_BIT_32((unsigned)enmType))
    2875                             aLEDs[enmType].u32 |= readAndClearLed(papSrcLeds[idxLed]);
    2876                     }
    2877                 /* Single-type drivers (e.g. floppy) have the type in ->enmType */
    2878                 else
    2879                 {
    2880                     uint32_t const idxType = ASMBitFirstSetU32(pLS->fTypes) - 1;
    2881                     for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++)
    2882                         aLEDs[idxType].u32 |= readAndClearLed(papSrcLeds[idxLed]);
    2883                 }
     2950                uint32_t const            cLeds       = maLedTypes[idxType].cLeds;
     2951                PPDMLED volatile ** const pappSrcLeds = maLedTypes[idxType].pappLeds;
     2952                for (size_t iLed = 0; iLed < cLeds; iLed++)
     2953                    aLEDs[idxType].u32 |= readAndClearLed(*pappSrcLeds[iLed]);
    28842954            }
    2885         }
    28862955    }
    28872956
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r98091 r98095  
    657657
    658658/**
     659 * Updates the device type for a LED.
     660 *
     661 * @param   penmSubTypeEntry    The sub-type entry to update.
     662 * @param   enmNewType          The new type.
     663 */
     664void Console::i_setLedType(DeviceType_T *penmSubTypeEntry, DeviceType_T enmNewType)
     665{
     666    /*
     667     * ASSUMES no race conditions here wrt concurrent type updating.
     668     */
     669    if (*penmSubTypeEntry != enmNewType)
     670    {
     671        *penmSubTypeEntry = enmNewType;
     672        ASMAtomicIncU32(&muLedGen);
     673    }
     674}
     675
     676
     677/**
    659678 * Allocate a set of LEDs.
    660679 *
     
    738757 * @throws ConfigError and std::bad_alloc.
    739758 */
    740 void Console::i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType)
     759void Console::i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType, uint32_t cLeds /*= 1*/)
    741760{
    742761    Assert(enmType > DeviceType_Null && enmType < DeviceType_End);
    743     i_attachStatusDriver(pCtlInst, RT_BIT_32(enmType), 1, NULL, NULL, NULL, 0);
     762    i_attachStatusDriver(pCtlInst, RT_BIT_32(enmType), cLeds, NULL, NULL, NULL, 0);
    744763}
    745764
     
    21842203                     * Attach the status driver.
    21852204                     */
    2186                     i_attachStatusDriver(pInst, RT_BIT_32(DeviceType_USB), 2, NULL, NULL, NULL, 0);
     2205                    i_attachStatusDriver(pInst, DeviceType_USB, 2);
    21872206                }
    21882207            } /* for every USB controller. */
     
    24852504
    24862505                    /* Attach the status driver */
    2487                     i_attachStatusDriver(pCtlInst, DeviceType_Floppy, 2, NULL,
    2488                                          &mapMediumAttachments, pszCtrlDev, ulInstance);
     2506                    i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_Floppy),
     2507                                         2, NULL, &mapMediumAttachments, pszCtrlDev, ulInstance);
    24892508                    break;
    24902509                }
     
    50975116
    50985117        if (paLedDevType)
    5099             paLedDevType[uLUN] = enmType;
     5118            i_setLedType(&paLedDevType[uLUN], enmType);
    51005119
    51015120        /* Dump the changed LUN if possible, dump the complete device otherwise */
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