VirtualBox

Changeset 98088 in vbox


Ignore:
Timestamp:
Jan 16, 2023 12:57:07 AM (23 months ago)
Author:
vboxsync
Message:

Main/ConsoleImpl: Added a dedicated read/write lock to the LED sets to protect potential activity queries during VM construction. bugref:9892

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

Legend:

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

    r98086 r98088  
    10681068    /** @name LEDs and their management
    10691069     * @{ */
     1070    /** Read/write lock separating LED allocations (write) from queries (read). */
     1071    RWLockHandle mLedLock;
    10701072    /** Number of LED sets in use in maLedSets. */
    10711073    uint32_t          mcLedSets;
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r98086 r98088  
    427427#endif
    428428    , mBusMgr(NULL)
     429    , mLedLock(LOCKCLASS_LISTOFOTHEROBJECTS /* must be higher than LOCKCLASS_OTHEROBJECT */)
    429430    , m_pKeyStore(NULL)
    430431    , mpIfSecKey(NULL)
     
    879880    }
    880881
    881     /* Release memory held by the LED sets. */
     882    /* Release memory held by the LED sets (no need to take lock). */
    882883    for (size_t idxSet = 0; idxSet < mcLedSets; idxSet++)
    883884    {
    884885        RTMemFree(maLedSets[idxSet].papLeds);
    885         RTMemFree(maLedSets[idxSet].paSubTypes);
    886886        maLedSets[idxSet].papLeds = NULL;
    887887        maLedSets[idxSet].paSubTypes = NULL;
     
    28282828{
    28292829    /*
    2830      * Note: we don't lock the console object here because
    2831      * readAndClearLed() should be thread safe.
    2832      */
    2833 /** @todo r=bird: readAndClearLed is safe, provided that we're not running at the
    2834  * same time as Console::i_allocateDriverLeds.  This assumption is not correct
    2835  * during VM construction. */
    2836 
    2837     /*
    28382830     * Make a roadmap of which DeviceType_T LED types are wanted:
    28392831     */
     
    28542846    /*
    28552847     * 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.
    28562852     */
    28572853    PDMLEDCORE aLEDs[DeviceType_End] = { {0} };
    28582854    Assert(aLEDs[1].u32 == 0 && aLEDs[DeviceType_End / 2].u32 == 0 && aLEDs[DeviceType_End - 1].u32 == 0); /* paranoia */
    2859     uint32_t idxSet = mcLedSets;
    2860     while (idxSet-- > 0)
    2861     {
    2862         /* Look inside this driver's set of LEDs and check if the types mask overlap with the request: */
    2863         PLEDSET pLS = &maLedSets[idxSet];
    2864         if (pLS->fTypes & fWanted)
    2865         {
    2866             uint32_t const        cLeds      = pLS->cLeds;
    2867             PPDMLED const * const papSrcLeds = pLS->papLeds;
    2868 
    2869             /* Multi-type drivers (e.g. SCSI) have a subtype array which must be matched. */
    2870             DeviceType_T const *paSubTypes = pLS->paSubTypes;
    2871             if (paSubTypes)
    2872                 for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++)
     2855    {
     2856        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)
     2863            {
     2864                uint32_t const        cLeds      = pLS->cLeds;
     2865                PPDMLED const * 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
    28732879                {
    2874                     DeviceType_T const enmType = paSubTypes[idxLed];
    2875                     Assert((unsigned)enmType < (unsigned)DeviceType_End);
    2876                     if (fWanted & RT_BIT_32((unsigned)enmType))
    2877                         aLEDs[enmType].u32 |= readAndClearLed(papSrcLeds[idxLed]);
     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]);
    28782883                }
    2879             /* Single-type drivers (e.g. floppy) have the type in ->enmType */
    2880             else
    2881             {
    2882                 uint32_t const idxType = ASMBitFirstSetU32(pLS->fTypes) - 1;
    2883                 for (uint32_t idxLed = 0; idxLed < cLeds; idxLed++)
    2884                     aLEDs[idxType].u32 |= readAndClearLed(papSrcLeds[idxLed]);
    28852884            }
    28862885        }
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r98086 r98088  
    674674    Assert(!(fTypes & (RT_BIT_32(DeviceType_Null) | ~(RT_BIT_32(DeviceType_End) - 1))));
    675675
    676     /* Grab a LED set entry before we start allocating anything so the destructor can do the cleanups. */
    677     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); /* Caller should have this already. Need protect mcLedSets check and update. */
    678     AssertStmt(mcLedSets < RT_ELEMENTS(maLedSets),
    679                throw ConfigError("AllocateDriverPapLeds", VERR_OUT_OF_RANGE, "Too many LED sets"));
    680     uint32_t const idxLedSet = mcLedSets++;
    681     PLEDSET pLS = &maLedSets[idxLedSet];
    682     pLS->papLeds = (PPDMLED *)RTMemAllocZ(sizeof(PPDMLED) * cLeds);
    683     AssertStmt(pLS->papLeds, throw E_OUTOFMEMORY);
    684     pLS->cLeds = cLeds;
    685     pLS->fTypes = fTypes;
    686     pLS->paSubTypes = NULL;
    687 
    688     if (ppaSubTypes)
     676    /* Preallocate the arrays we need, bunching them together. */
     677    AssertCompile((unsigned)DeviceType_Null == 0);
     678    PPDMLED *papLeds = (PPDMLED *)RTMemAllocZ((sizeof(PPDMLED) + (ppaSubTypes ? sizeof(**ppaSubTypes) : 0)) * cLeds);
     679    AssertStmt(papLeds, throw E_OUTOFMEMORY);
     680
     681    /* Take the LED lock in allocation mode and see if there are more LED set entries availalbe. */
    689682    {
    690         AssertCompile((unsigned)DeviceType_Null == 0);
    691         *ppaSubTypes = pLS->paSubTypes = (DeviceType_T *)RTMemAllocZ(sizeof(DeviceType_T) * cLeds);
    692         AssertStmt(pLS->paSubTypes, throw E_OUTOFMEMORY);
     683        AutoWriteLock alock(mLedLock COMMA_LOCKVAL_SRC_POS);
     684        uint32_t const idxLedSet = mcLedSets;
     685        if (idxLedSet < RT_ELEMENTS(maLedSets))
     686        {
     687            /* Initialize the set and return the index. */
     688            PLEDSET pLS = &maLedSets[idxLedSet];
     689            pLS->papLeds = papLeds;
     690            pLS->cLeds = cLeds;
     691            pLS->fTypes = fTypes;
     692            if (ppaSubTypes)
     693                 *ppaSubTypes = pLS->paSubTypes = (DeviceType_T *)&papLeds[cLeds];
     694            else
     695                pLS->paSubTypes = NULL;
     696
     697            mcLedSets = idxLedSet + 1;
     698            LogRel2(("return idxLedSet=%d (mcLedSets=%u out of max %zu)\n", idxLedSet, mcLedSets, RT_ELEMENTS(maLedSets)));
     699            return idxLedSet;
     700        }
    693701    }
    694702
    695     LogRel2(("mcLedSets = %d, RT_ELEMENTS(maLedSets) = %d\n", mcLedSets, RT_ELEMENTS(maLedSets)));
    696     return idxLedSet;
     703    RTMemFree(papLeds);
     704    AssertFailed();
     705    throw ConfigError("AllocateDriverPapLeds", VERR_OUT_OF_RANGE, "Too many LED sets");
    697706}
    698707
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