VirtualBox

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


Ignore:
Timestamp:
Jun 15, 2011 12:44:16 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
72280
Message:

VMM,Devices: Automatically use a per-device lock instead of the giant IOM lock. With exception of the PIC, APIC, IOAPIC and PCI buses which are all using the PDM crit sect, there should be no calls between devices. So, this change should be relatively safe.

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

Legend:

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

    r37452 r37466  
    9494}
    9595
     96
    9697/**
    9798 * Returns the contents of register or immediate data of instruction's parameter.
     
    316317        void           *pvUser    = pRange->pvUser;
    317318        PPDMDEVINS      pDevIns   = pRange->pDevIns;
    318         PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     319        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSectRo);
    319320
    320321        /*
     
    512513        void           *pvUser    = pRange->pvUser;
    513514        PPDMDEVINS      pDevIns   = pRange->pDevIns;
    514         PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     515        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSectRo);
    515516
    516517        /*
     
    680681        }
    681682#endif
    682         void           *pvUser    =  pRange->pvUser;
     683        void           *pvUser    = pRange->pvUser;
    683684        PPDMDEVINS      pDevIns   = pRange->pDevIns;
    684         PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     685        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSectRo);
    685686
    686687        /*
     
    852853        void           *pvUser    = pRange->pvUser;
    853854        PPDMDEVINS      pDevIns   = pRange->pDevIns;
    854         PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     855        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSectRo);
    855856
    856857        /*
  • trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp

    r37452 r37466  
    11371137    iomMmioRetainRange(pRange);
    11381138    PPDMDEVINS pDevIns = pRange->CTX_SUFF(pDevIns);
    1139     PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSect);
     1139    PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSectRo);
    11401140    if (!pLock)
    11411141        pLock = &pVM->iom.s.EmtLock;
     
    13761376    iomMmioRetainRange(pRange);
    13771377    PPDMDEVINS pDevIns = pRange->CTX_SUFF(pDevIns);
    1378     PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSect);
     1378    PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSectRo);
    13791379    if (!pLock)
    13801380        pLock = &pVM->iom.s.EmtLock;
     
    14601460        iomMmioRetainRange(pRange);
    14611461        PPDMDEVINS pDevIns = pRange->CTX_SUFF(pDevIns);
    1462         PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSect);
     1462        PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSectRo);
    14631463        if (!pLock)
    14641464            pLock = &pVM->iom.s.EmtLock;
     
    16101610        iomMmioRetainRange(pRange);
    16111611        PPDMDEVINS pDevIns = pRange->CTX_SUFF(pDevIns);
    1612         PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSect);
     1612        PPDMCRITSECT pLock = pDevIns->CTX_SUFF(pCritSectRo);
    16131613        if (!pLock)
    16141614            pLock = &pVM->iom.s.EmtLock;
  • trunk/src/VBox/VMM/VMMR3/IOM.cpp

    r37452 r37466  
    159159     * Initialize the REM critical section.
    160160     */
    161     int rc = PDMR3CritSectInit(pVM, &pVM->iom.s.EmtLock, RT_SRC_POS, "IOM EMT Lock");
     161    int rc = PDMR3CritSectInit(pVM, &pVM->iom.s.EmtLock, RT_SRC_POS, "IOM Lock");
    162162    AssertRCReturn(rc, rc);
    163163
     
    17071707
    17081708/**
    1709  * For TM only!
    1710  *
    1711  * @returns Pointer to the critical section.
    1712  * @param   pVM                 The VM handle.
    1713  */
    1714 VMMR3DECL(PPDMCRITSECT) IOMR3GetCritSect(PVM pVM)
    1715 {
    1716     return &pVM->iom.s.EmtLock;
    1717 }
    1718 
    1719 
    1720 /**
    17211709 * Display a single MMIO range.
    17221710 *
  • trunk/src/VBox/VMM/VMMR3/PDM.cpp

    r37443 r37466  
    366366        rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.CritSect, RT_SRC_POS, "PDM");
    367367    if (RT_SUCCESS(rc))
    368         rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.GiantDevCritSect, RT_SRC_POS, "Giant PDM Dev");
    369     if (RT_SUCCESS(rc))
    370368    {
    371369        rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.NopCritSect, RT_SRC_POS, "NOP");
     
    507505            pDevIns->pHlpRC             = pDevHlpRC;
    508506            pDevIns->pvInstanceDataRC   = MMHyperR3ToRC(pVM, pDevIns->pvInstanceDataR3);
    509             if (pDevIns->pCritSectR3)
    510                 pDevIns->pCritSectRC    = MMHyperR3ToRC(pVM, pDevIns->pCritSectR3);
     507            if (pDevIns->pCritSectRoR3)
     508                pDevIns->pCritSectRoRC  = MMHyperR3ToRC(pVM, pDevIns->pCritSectRoR3);
    511509            pDevIns->Internal.s.pVMRC   = pVM->pVMRC;
    512510            if (pDevIns->Internal.s.pPciBusR3)
  • trunk/src/VBox/VMM/VMMR3/PDMCritSect.cpp

    r37443 r37466  
    165165                pCritSect->pVMRC                     = pVM->pVMRC;
    166166                pCritSect->pvKey                     = pvKey;
     167                pCritSect->fAutomaticDefaultCritsect = false;
     168                pCritSect->fUsedByTimerOrSimilar     = false;
    167169                pCritSect->EventToSignal             = NIL_RTSEMEVENT;
    168170                pCritSect->pNext                     = pVM->pUVM->pdm.s.pCritSects;
     
    236238{
    237239    return pdmR3CritSectInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
     240}
     241
     242
     243/**
     244 * Initializes the automatic default PDM critical section for a device.
     245 *
     246 * @returns VBox status code.
     247 * @param   pVM             The VM handle.
     248 * @param   pDevIns         Device instance.
     249 * @param   pCritSect       Pointer to the critical section.
     250 */
     251int pdmR3CritSectInitDeviceAuto(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
     252                                const char *pszNameFmt, ...)
     253{
     254    va_list va;
     255    va_start(va, pszNameFmt);
     256    int rc = pdmR3CritSectInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
     257    if (RT_SUCCESS(rc))
     258        pCritSect->s.fAutomaticDefaultCritsect = true;
     259    va_end(va);
     260    return rc;
    238261}
    239262
  • trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp

    r37452 r37466  
    15831583             pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
    15841584    return pCritSect;
     1585}
     1586
     1587
     1588/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
     1589static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
     1590{
     1591    /*
     1592     * Validate input.
     1593     *
     1594     * Note! We only allow the automatically created default critical section
     1595     *       to be replaced by this API.
     1596     */
     1597    PDMDEV_ASSERT_DEVINS(pDevIns);
     1598    AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
     1599    LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
     1600             pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
     1601    AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
     1602    PVM pVM = pDevIns->Internal.s.pVMR3;
     1603    AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
     1604
     1605    VM_ASSERT_EMT(pVM);
     1606    VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
     1607
     1608    AssertReturn(pDevIns->pCritSectRoR3, VERR_INTERNAL_ERROR_4);
     1609    AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
     1610    AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
     1611    AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
     1612
     1613    /*
     1614     * Replace the critical section and destroy the automatic default section.
     1615     */
     1616    PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
     1617    pDevIns->pCritSectRoR3 = pCritSect;
     1618    if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
     1619        pDevIns->pCritSectRoR0 = MMHyperCCToR0(pVM, pDevIns->pCritSectRoR3);
     1620    else
     1621        Assert(pDevIns->pCritSectRoR0 == NIL_RTRCPTR);
     1622
     1623    if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
     1624        pDevIns->pCritSectRoRC = MMHyperCCToRC(pVM, pDevIns->pCritSectRoR3);
     1625    else
     1626        Assert(pDevIns->pCritSectRoRC == NIL_RTRCPTR);
     1627
     1628    PDMR3CritSectDelete(pOldCritSect);
     1629    if (pDevIns->pReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0))
     1630        MMHyperFree(pVM, pOldCritSect);
     1631    else
     1632        MMR3HeapFree(pOldCritSect);
     1633
     1634    LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
     1635    return VINF_SUCCESS;
    15851636}
    15861637
     
    32633314    pdmR3DevHlp_CritSectGetNopR0,
    32643315    pdmR3DevHlp_CritSectGetNopRC,
     3316    pdmR3DevHlp_SetDeviceCritSect,
    32653317    pdmR3DevHlp_ThreadCreate,
    32663318    pdmR3DevHlp_SetAsyncNotification,
     
    34783530    pdmR3DevHlp_CritSectGetNopR0,
    34793531    pdmR3DevHlp_CritSectGetNopRC,
     3532    pdmR3DevHlp_SetDeviceCritSect,
    34803533    pdmR3DevHlp_ThreadCreate,
    34813534    pdmR3DevHlp_SetAsyncNotification,
  • trunk/src/VBox/VMM/VMMR3/PDMDevice.cpp

    r35810 r37466  
    288288
    289289        /*
    290          * Allocate the device instance.
     290         * Allocate the device instance and critical section.
    291291         */
    292292        AssertReturn(paDevs[i].pDev->cInstances < paDevs[i].pDev->pReg->cMaxInstances, VERR_PDM_TOO_MANY_DEVICE_INSTANCES);
     
    298298        else
    299299            rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, cb, (void **)&pDevIns);
    300         if (RT_FAILURE(rc))
    301         {
    302             AssertMsgFailed(("Failed to allocate %d bytes of instance data for device '%s'. rc=%Rrc\n",
    303                              cb, paDevs[i].pDev->pReg->szName, rc));
    304             return rc;
    305         }
     300        AssertLogRelMsgRCReturn(rc,
     301                                ("Failed to allocate %d bytes of instance data for device '%s'. rc=%Rrc\n",
     302                                cb, paDevs[i].pDev->pReg->szName, rc),
     303                                rc);
     304        PPDMCRITSECT pCritSect;
     305        if (paDevs[i].pDev->pReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0))
     306            rc = MMHyperAlloc(pVM, sizeof(*pCritSect), 0, MM_TAG_PDM_DEVICE, (void **)&pCritSect);
     307        else
     308            rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, sizeof(*pCritSect), (void **)&pCritSect);
     309        AssertLogRelMsgRCReturn(rc, ("Failed to allocate a critical section for the device\n",  rc), rc);
    306310
    307311        /*
     
    335339        pDevIns->pvInstanceDataR0               = pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0
    336340                                                ? MMHyperR3ToR0(pVM, pDevIns->pvInstanceDataR3) : NIL_RTR0PTR;
    337         //pDevIns->pCritSectR3                    = NULL;
    338         //pDevIns->pCritSectR0                    = NIL_RTR0PTR;
    339         //pDevIns->pCritSectRC                    = NIL_RTRCPTR;
     341
     342        pDevIns->pCritSectRoR3                  = pCritSect;
     343        pDevIns->pCritSectRoRC                  = pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC
     344                                                ? MMHyperR3ToRC(pVM, pCritSect) : NIL_RTRCPTR;
     345        pDevIns->pCritSectRoR0                  = pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0
     346                                                ? MMHyperR3ToR0(pVM, pCritSect) : NIL_RTR0PTR;
     347
     348        rc = pdmR3CritSectInitDeviceAuto(pVM, pDevIns, pCritSect, RT_SRC_POS,
     349                                         "%s#%u Auto", pDevIns->pReg->szName, pDevIns->iInstance);
     350        AssertLogRelRCReturn(rc, rc);
    340351
    341352        /*
     
    370381        Log(("PDM: Constructing device '%s' instance %d...\n", pDevIns->pReg->szName, pDevIns->iInstance));
    371382        rc = pDevIns->pReg->pfnConstruct(pDevIns, pDevIns->iInstance, pDevIns->pCfg);
    372         if (RT_SUCCESS(rc))
    373         {
    374             /*
    375              * Per-device critsect fun.
    376              */
    377             if (pDevIns->pCritSectR3)
    378             {
    379                 AssertStmt(PDMCritSectIsInitialized(pDevIns->pCritSectR3), rc = VERR_INTERNAL_ERROR_4);
    380                 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
    381                 {
    382                     pDevIns->pCritSectR0 = MMHyperCCToR0(pVM, pDevIns->pCritSectR3);
    383                     AssertStmt(pDevIns->pCritSectR0 != NIL_RTR0PTR, rc = VERR_INTERNAL_ERROR_3);
    384                 }
    385                 else
    386                     AssertStmt(pDevIns->pCritSectR0 == NIL_RTRCPTR, rc = VERR_INTERNAL_ERROR_2);
    387 
    388                 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
    389                 {
    390                     pDevIns->pCritSectRC = MMHyperCCToRC(pVM, pDevIns->pCritSectR3);
    391                     AssertStmt(pDevIns->pCritSectRC != NIL_RTRCPTR, rc = VERR_INTERNAL_ERROR_3);
    392                 }
    393                 else
    394                     AssertStmt(pDevIns->pCritSectRC == NIL_RTRCPTR, rc = VERR_INTERNAL_ERROR_2);
    395             }
    396             else
    397                 AssertStmt(   pDevIns->pCritSectRC == NIL_RTRCPTR
    398                            && pDevIns->pCritSectR0 == NIL_RTR0PTR,
    399                            rc = VERR_INTERNAL_ERROR_5);
    400         }
    401383        if (RT_FAILURE(rc))
    402384        {
    403385            LogRel(("PDM: Failed to construct '%s'/%d! %Rra\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    404386            paDevs[i].pDev->cInstances--;
    405             /* because we're damn lazy right now, we'll say that the destructor will be called even if the constructor fails. */
     387            /* Because we're damn lazy, the destructor will be called even if
     388               the constructor fails.  So, no unlinking. */
    406389            return rc == VERR_VERSION_MISMATCH ? VERR_PDM_DEVICE_VERSION_MISMATCH : rc;
    407390        }
     
    855838
    856839/**
     840 * References the critical section associated with a device for the use by a
     841 * timer or similar created by the device.
     842 *
     843 * @returns Pointer to the critical section.
     844 * @param   pVM             The VM handle.
     845 * @param   pDevIns         The device instance in question.
     846 *
     847 * @internal
     848 */
     849VMMR3_INT_DECL(PPDMCRITSECT) PDMR3DevGetCritSect(PVM pVM, PPDMDEVINS pDevIns)
     850{
     851    VM_ASSERT_EMT(pVM);
     852    VM_ASSERT_STATE(pVM, VMSTATE_CREATING);
     853    AssertPtr(pDevIns);
     854
     855    PPDMCRITSECT pCritSect = pDevIns->pCritSectRoR3;
     856    AssertPtr(pCritSect);
     857    pCritSect->s.fUsedByTimerOrSimilar = true;
     858
     859    return pCritSect;
     860}
     861
     862
     863/**
    857864 * Attaches a preconfigured driver to an existing device or driver instance.
    858865 *
  • trunk/src/VBox/VMM/VMMR3/TM.cpp

    r37452 r37466  
    13321332        (*ppTimer)->pvUser          = pvUser;
    13331333        if (!(fFlags & TMTIMER_FLAGS_NO_CRIT_SECT))
    1334         {
    1335             if (pDevIns->pCritSectR3)
    1336                 (*ppTimer)->pCritSect = pDevIns->pCritSectR3;
    1337             else
    1338                 (*ppTimer)->pCritSect = IOMR3GetCritSect(pVM);
    1339         }
     1334            (*ppTimer)->pCritSect = PDMR3DevGetCritSect(pVM, pDevIns);
    13401335        Log(("TM: Created device timer %p clock %d callback %p '%s'\n", (*ppTimer), enmClock, pfnCallback, pszDesc));
    13411336    }
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r37443 r37466  
    268268    /** Pointer to the VM - GCPtr. */
    269269    PVMRC                           pVMRC;
     270    /** Set if this critical section is the automatically created default
     271     * section of a device.. */
     272    bool                            fAutomaticDefaultCritsect;
     273    /** Set if the critical section is used by a timer or similar.
     274     * See PDMR3DevGetCritSect.  */
     275    bool                            fUsedByTimerOrSimilar;
    270276    /** Alignment padding. */
    271     uint32_t                        padding;
     277    bool                            afPadding[2];
    272278    /** Event semaphore that is scheduled to be signaled upon leaving the
    273279     * critical section. This is Ring-3 only of course. */
     
    951957     * the PIC, APIC, IOAPIC and PCI devices plus some PDM functions. */
    952958    PDMCRITSECT                     CritSect;
    953 
    954     /** The giant PDM device lock.
    955      * This is a temporary measure and will be removed. */
    956     PDMCRITSECT                     GiantDevCritSect;
    957 
    958959    /** The NOP critical section.
    959960     * This is a dummy critical section that will not do any thread
     
    11261127void        pdmR3CritSectRelocate(PVM pVM);
    11271128int         pdmR3CritSectInitDevice(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, va_list va);
     1129int         pdmR3CritSectInitDeviceAuto(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
     1130                                        const char *pszNameFmt, ...);
    11281131int         pdmR3CritSectDeleteDevice(PVM pVM, PPDMDEVINS pDevIns);
    11291132int         pdmR3CritSectInitDriver(PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...);
  • trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp

    r37452 r37466  
    291291    GEN_CHECK_SIZE(PDM);
    292292    GEN_CHECK_OFF(PDM, CritSect);
    293     GEN_CHECK_OFF(PDM, GiantDevCritSect);
    294293    GEN_CHECK_OFF(PDM, NopCritSect);
    295294    GEN_CHECK_OFF(PDM, pDevs);
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