VirtualBox

Changeset 45152 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Mar 23, 2013 8:36:23 PM (12 years ago)
Author:
vboxsync
Message:

PDMCritSectRw: Early morphing stage - untested, ring-3 only.

Location:
trunk/src/VBox/VMM/VMMR3
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r45108 r45152  
    14091409
    14101410    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PDM_CRITSECT))
    1411         PDMCritSectFF(pVCpu);
     1411        PDMCritSectBothFF(pVCpu);
    14121412
    14131413    /* Update CR3 (Nested Paging case for HM). */
  • trunk/src/VBox/VMM/VMMR3/PDM.cpp

    r45024 r45152  
    343343    pUVM->pdm.s.pModules   = NULL;
    344344    pUVM->pdm.s.pCritSects = NULL;
     345    pUVM->pdm.s.pRwCritSects = NULL;
    345346    return RTCritSectInit(&pUVM->pdm.s.ListCritSect);
    346347}
     
    374375     * Initialize critical sections first.
    375376     */
    376     int rc = pdmR3CritSectInitStats(pVM);
     377    int rc = pdmR3CritSectBothInitStats(pVM);
    377378    if (RT_SUCCESS(rc))
    378379        rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.CritSect, RT_SRC_POS, "PDM");
     
    458459     * Critical sections.
    459460     */
    460     pdmR3CritSectRelocate(pVM);
     461    pdmR3CritSectBothRelocate(pVM);
    461462
    462463    /*
     
    660661        TMR3TimerDestroyDevice(pVM, pDevIns);
    661662        SSMR3DeregisterDevice(pVM, pDevIns, NULL, 0);
    662         pdmR3CritSectDeleteDevice(pVM, pDevIns);
     663        pdmR3CritSectBothDeleteDevice(pVM, pDevIns);
    663664        pdmR3ThreadDestroyDevice(pVM, pDevIns);
    664665        PDMR3QueueDestroyDevice(pVM, pDevIns);
     
    702703     */
    703704    PDMR3CritSectDelete(&pVM->pdm.s.CritSect);
    704     /* The MiscCritSect is deleted by PDMR3CritSectTerm. */
     705    /* The MiscCritSect is deleted by PDMR3CritSectBothTerm later. */
    705706
    706707    LogFlow(("PDMR3Term: returns %Rrc\n", VINF_SUCCESS));
     
    726727
    727728    Assert(pUVM->pdm.s.pCritSects == NULL);
     729    Assert(pUVM->pdm.s.pRwCritSects == NULL);
    728730    RTCritSectDelete(&pUVM->pdm.s.ListCritSect);
    729731}
  • trunk/src/VBox/VMM/VMMR3/PDMCritSect.cpp

    r44528 r45152  
    2323#include "PDMInternal.h"
    2424#include <VBox/vmm/pdmcritsect.h>
     25#include <VBox/vmm/pdmcritsectrw.h>
    2526#include <VBox/vmm/mm.h>
    2627#include <VBox/vmm/vm.h>
     
    4142*******************************************************************************/
    4243static int pdmR3CritSectDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal);
     44static int pdmR3CritSectRwDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTRWINT pCritSect, PPDMCRITSECTRWINT pPrev, bool fFinal);
    4345
    4446
     
    5052 * @param   pVM         Pointer to the VM.
    5153 */
    52 int pdmR3CritSectInitStats(PVM pVM)
     54int pdmR3CritSectBothInitStats(PVM pVM)
    5355{
    5456    STAM_REG(pVM, &pVM->pdm.s.StatQueuedCritSectLeaves, STAMTYPE_COUNTER, "/PDM/QueuedCritSectLeaves", STAMUNIT_OCCURENCES,
     
    6365 * @param   pVM         Pointer to the VM.
    6466 */
    65 void pdmR3CritSectRelocate(PVM pVM)
     67void pdmR3CritSectBothRelocate(PVM pVM)
    6668{
    6769    PUVM pUVM = pVM->pUVM;
     
    6971
    7072    for (PPDMCRITSECTINT pCur = pUVM->pdm.s.pCritSects;
     73         pCur;
     74         pCur = pCur->pNext)
     75        pCur->pVMRC = pVM->pVMRC;
     76
     77    for (PPDMCRITSECTRWINT pCur = pUVM->pdm.s.pRwCritSects;
    7178         pCur;
    7279         pCur = pCur->pNext)
     
    9198 * @remark  Don't confuse this with PDMR3CritSectDelete.
    9299 */
    93 VMMDECL(int) PDMR3CritSectTerm(PVM pVM)
     100VMMR3_INT_DECL(int) PDMR3CritSectBothTerm(PVM pVM)
    94101{
    95102    PUVM    pUVM = pVM->pUVM;
     
    100107    {
    101108        int rc2 = pdmR3CritSectDeleteOne(pVM, pUVM, pUVM->pdm.s.pCritSects, NULL, true /* final */);
     109        AssertRC(rc2);
     110        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     111            rc = rc2;
     112    }
     113
     114    while (pUVM->pdm.s.pRwCritSects)
     115    {
     116        int rc2 = pdmR3CritSectRwDeleteOne(pVM, pUVM, pUVM->pdm.s.pRwCritSects, NULL, true /* final */);
    102117        AssertRC(rc2);
    103118        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     
    127142{
    128143    VM_ASSERT_EMT(pVM);
     144    Assert(pCritSect->Core.u32Magic != RTCRITSECT_MAGIC);
    129145
    130146    /*
     
    168184                pCritSect->fUsedByTimerOrSimilar     = false;
    169185                pCritSect->EventToSignal             = NIL_RTSEMEVENT;
    170                 pCritSect->pNext                     = pVM->pUVM->pdm.s.pCritSects;
    171186                pCritSect->pszName                   = pszName;
    172                 pVM->pUVM->pdm.s.pCritSects = pCritSect;
     187
    173188                STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLock,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZLock", pCritSect->pszName);
    174189                STAMR3RegisterF(pVM, &pCritSect->StatContentionRZUnlock,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZUnlock", pCritSect->pszName);
     
    177192                STAMR3RegisterF(pVM, &pCritSect->StatLocked,        STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSects/%s/Locked", pCritSect->pszName);
    178193#endif
     194
     195                PUVM pUVM = pVM->pUVM;
     196                RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     197                pCritSect->pNext = pUVM->pdm.s.pCritSects;
     198                pUVM->pdm.s.pCritSects = pCritSect;
     199                RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     200
    179201                return VINF_SUCCESS;
    180202            }
     
    191213
    192214/**
     215 * Initializes a read/write critical section and inserts it into the list.
     216 *
     217 * @returns VBox status code.
     218 * @param   pVM             Pointer to the VM.
     219 * @param   pCritSect       The read/write critical section.
     220 * @param   pvKey           The owner key.
     221 * @param   RT_SRC_POS_DECL The source position.
     222 * @param   pszName         The name of the critical section (for statistics).
     223 * @param   pszNameFmt      Format string for naming the critical section.  For
     224 *                          statistics and lock validation.
     225 * @param   va              Arguments for the format string.
     226 */
     227static int pdmR3CritSectRwInitOne(PVM pVM, PPDMCRITSECTRWINT pCritSect, void *pvKey, RT_SRC_POS_DECL,
     228                                  const char *pszNameFmt, va_list va)
     229{
     230    VM_ASSERT_EMT(pVM);
     231    Assert(pCritSect->Core.u32Magic != RTCRITSECTRW_MAGIC);
     232
     233    /*
     234     * Allocate the semaphores.
     235     */
     236    AssertCompile(sizeof(SUPSEMEVENT) == sizeof(pCritSect->Core.hEvtWrite));
     237    int rc = SUPSemEventCreate(pVM->pSession, (PSUPSEMEVENT)&pCritSect->Core.hEvtWrite);
     238    if (RT_SUCCESS(rc))
     239    {
     240        AssertCompile(sizeof(SUPSEMEVENTMULTI) == sizeof(pCritSect->Core.hEvtRead));
     241        rc = SUPSemEventMultiCreate(pVM->pSession, (PSUPSEMEVENT)&pCritSect->Core.hEvtRead);
     242        if (RT_SUCCESS(rc))
     243        {
     244            /* Only format the name once. */
     245            char *pszName = RTStrAPrintf2V(pszNameFmt, va); /** @todo plug the "leak"... */
     246            if (pszName)
     247            {
     248                pCritSect->Core.pValidatorRead  = NULL;
     249                pCritSect->Core.pValidatorWrite = NULL;
     250#ifdef PDMCRITSECT_STRICT
     251# ifdef RT_LOCK_STRICT_ORDER
     252                RTLOCKVALCLASS hClass = RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, "%s", pszName);
     253# else
     254                RTLOCKVALCLASS hClass = NIL_RTLOCKVALCLASS;
     255# endif
     256                rc = RTLockValidatorRecExclCreate(&pCritSect->Core.pValidatorWrite, hClass, RTLOCKVAL_SUB_CLASS_NONE,
     257                                                  pCritSect, true, "%s", pszName);
     258                if (RT_SUCCESS(rc))
     259                    rc = RTLockValidatorRecSharedCreate(&pCritSect->Core.pValidatorRead, hClass, RTLOCKVAL_SUB_CLASS_NONE,
     260                                                        pCritSect, false /*fSignaller*/, true, "%s", pszName);
     261#endif
     262                if (RT_SUCCESS(rc))
     263                {
     264                    /*
     265                     * Initialize the structure (first bit is c&p from RTCritSectRwInitEx).
     266                     */
     267                    pCritSect->Core.u32Magic             = RTCRITSECTRW_MAGIC_DEAD;
     268                    pCritSect->Core.fNeedReset           = false;
     269                    pCritSect->Core.u64State             = 0;
     270                    pCritSect->Core.hNativeWriter        = NIL_RTNATIVETHREAD;
     271                    pCritSect->Core.cWriterReads         = 0;
     272                    pCritSect->Core.cWriteRecursions     = 0;
     273                    pCritSect->Core.pValidatorWrite      = NULL;
     274                    pCritSect->Core.pValidatorRead       = NULL;
     275#if HC_ARCH_BITS == 32
     276                    pCritSect->Core.HCPtrPadding         = NIL_RTHCPTR;
     277#endif
     278                    pCritSect->pVMR3                     = pVM;
     279                    pCritSect->pVMR0                     = pVM->pVMR0;
     280                    pCritSect->pVMRC                     = pVM->pVMRC;
     281                    pCritSect->pvKey                     = pvKey;
     282                    pCritSect->pszName                   = pszName;
     283
     284                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZEnterExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZEnterExcl", pCritSect->pszName);
     285                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLeaveExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZLeaveExcl", pCritSect->pszName);
     286                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZEnterShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZEnterShared", pCritSect->pszName);
     287                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLeaveShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZLeaveShared", pCritSect->pszName);
     288                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3EnterExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3EnterExcl", pCritSect->pszName);
     289                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3EnterShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3EnterShared", pCritSect->pszName);
     290                    STAMR3RegisterF(pVM, &pCritSect->StatRZEnterExcl,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/RZEnterExcl", pCritSect->pszName);
     291                    STAMR3RegisterF(pVM, &pCritSect->StatRZEnterShared,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/RZEnterShared", pCritSect->pszName);
     292                    STAMR3RegisterF(pVM, &pCritSect->StatR3EnterExcl,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/R3EnterExcl", pCritSect->pszName);
     293                    STAMR3RegisterF(pVM, &pCritSect->StatR3EnterShared,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/R3EnterShared", pCritSect->pszName);
     294#ifdef VBOX_WITH_STATISTICS
     295                    STAMR3RegisterF(pVM, &pCritSect->StatWriteLocked,         STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSectsRw/%s/WriteLocked", pCritSect->pszName);
     296#endif
     297
     298                    PUVM pUVM = pVM->pUVM;
     299                    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     300                    pCritSect->pNext = pUVM->pdm.s.pRwCritSects;
     301                    pUVM->pdm.s.pRwCritSects = pCritSect;
     302                    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     303
     304                    return VINF_SUCCESS;
     305                }
     306
     307                RTStrFree(pszName);
     308            }
     309            else
     310                rc = VERR_NO_STR_MEMORY;
     311            SUPSemEventMultiClose(pVM->pSession, (SUPSEMEVENT)pCritSect->Core.hEvtRead);
     312        }
     313        SUPSemEventClose(pVM->pSession, (SUPSEMEVENT)pCritSect->Core.hEvtWrite);
     314    }
     315    return rc;
     316}
     317
     318
     319/**
    193320 * Initializes a PDM critical section for internal use.
    194321 *
    195322 * The PDM critical sections are derived from the IPRT critical sections, but
    196  * works in GC as well.
     323 * works in ring-0 and raw-mode context as well.
    197324 *
    198325 * @returns VBox status code.
     
    204331 *                          statistics and lock validation.
    205332 * @param   ...             Arguments for the format string.
    206  * @thread  EMT(0)
     333 * @thread  EMT
    207334 */
    208335VMMR3DECL(int) PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...)
     
    221348
    222349/**
     350 * Initializes a PDM read/write critical section for internal use.
     351 *
     352 * The PDM read/write critical sections are derived from the IPRT read/write
     353 * critical sections, but works in ring-0 and raw-mode context as well.
     354 *
     355 * @returns VBox status code.
     356 * @param   pVM             Pointer to the VM.
     357 * @param   pDevIns         Device instance.
     358 * @param   pCritSect       Pointer to the read/write critical section.
     359 * @param   RT_SRC_POS_DECL Use RT_SRC_POS.
     360 * @param   pszNameFmt      Format string for naming the critical section.  For
     361 *                          statistics and lock validation.
     362 * @param   ...             Arguments for the format string.
     363 * @thread  EMT
     364 */
     365VMMR3DECL(int) PDMR3CritSectRwInit(PVM pVM, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...)
     366{
     367#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
     368    AssertCompile(sizeof(pCritSect->padding) >= sizeof(pCritSect->s));
     369#endif
     370    Assert(RT_ALIGN_P(pCritSect, sizeof(uintptr_t)) == pCritSect);
     371    va_list va;
     372    va_start(va, pszNameFmt);
     373    int rc = pdmR3CritSectRwInitOne(pVM, &pCritSect->s, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
     374    va_end(va);
     375    return rc;
     376}
     377
     378
     379/**
    223380 * Initializes a PDM critical section for a device.
    224  *
    225  * The PDM critical sections are derived from the IPRT critical sections, but
    226  * works in GC as well.
    227381 *
    228382 * @returns VBox status code.
     
    238392{
    239393    return pdmR3CritSectInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
     394}
     395
     396
     397/**
     398 * Initializes a PDM read/write critical section for a device.
     399 *
     400 * @returns VBox status code.
     401 * @param   pVM             Pointer to the VM.
     402 * @param   pDevIns         Device instance.
     403 * @param   pCritSect       Pointer to the read/write critical section.
     404 * @param   pszNameFmt      Format string for naming the critical section.  For
     405 *                          statistics and lock validation.
     406 * @param   va              Arguments for the format string.
     407 */
     408int pdmR3CritSectRwInitDevice(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     409                              const char *pszNameFmt, va_list va)
     410{
     411    return pdmR3CritSectRwInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
    240412}
    241413
     
    279451    va_start(va, pszNameFmt);
    280452    int rc = pdmR3CritSectInitOne(pVM, &pCritSect->s, pDrvIns, RT_SRC_POS_ARGS, pszNameFmt, va);
     453    va_end(va);
     454    return rc;
     455}
     456
     457
     458/**
     459 * Initializes a PDM read/write critical section for a driver.
     460 *
     461 * @returns VBox status code.
     462 * @param   pVM             Pointer to the VM.
     463 * @param   pDrvIns         Driver instance.
     464 * @param   pCritSect       Pointer to the read/write critical section.
     465 * @param   pszNameFmt      Format string for naming the critical section.  For
     466 *                          statistics and lock validation.
     467 * @param   ...             Arguments for the format string.
     468 */
     469int pdmR3CritSectRwInitDriver(PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     470                              const char *pszNameFmt, ...)
     471{
     472    va_list va;
     473    va_start(va, pszNameFmt);
     474    int rc = pdmR3CritSectRwInitOne(pVM, &pCritSect->s, pDrvIns, RT_SRC_POS_ARGS, pszNameFmt, va);
    281475    va_end(va);
    282476    return rc;
     
    349543
    350544/**
     545 * Deletes one read/write critical section.
     546 *
     547 * @returns VBox status code.
     548 *
     549 * @param   pVM         Pointer to the VM.
     550 * @param   pCritSect   The read/write critical section.
     551 * @param   pPrev       The previous critical section in the list.
     552 * @param   fFinal      Set if this is the final call and statistics shouldn't be deregistered.
     553 *
     554 * @remarks Caller must have entered the ListCritSect.
     555 */
     556static int pdmR3CritSectRwDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTRWINT pCritSect, PPDMCRITSECTRWINT pPrev, bool fFinal)
     557{
     558    /*
     559     * Assert free waiters and so on (c&p from RTCritSectRwDelete).
     560     */
     561    Assert(pCritSect->Core.u32Magic == RTCRITSECTRW_MAGIC);
     562    //Assert(pCritSect->Core.cNestings == 0);
     563    //Assert(pCritSect->Core.cLockers == -1);
     564    Assert(pCritSect->Core.hNativeWriter == NIL_RTNATIVETHREAD);
     565
     566    /*
     567     * Invalidate the structure and free the semaphores.
     568     */
     569    if (!ASMAtomicCmpXchgU32(&pCritSect->Core.u32Magic, RTCRITSECTRW_MAGIC_DEAD, RTCRITSECTRW_MAGIC))
     570        AssertFailed();
     571
     572    /*
     573     * Unlink it.
     574     */
     575    if (pPrev)
     576        pPrev->pNext = pCritSect->pNext;
     577    else
     578        pUVM->pdm.s.pRwCritSects = pCritSect->pNext;
     579
     580    /*
     581     * Delete it (parts taken from RTCritSectRwDelete).
     582     * In case someone is waiting we'll signal the semaphore cLockers + 1 times.
     583     */
     584    pCritSect->Core.fFlags   = 0;
     585    pCritSect->Core.u64State = 0;
     586
     587    SUPSEMEVENT      hEvtWrite = (SUPSEMEVENT)pCritSect->Core.hEvtWrite;
     588    pCritSect->Core.hEvtWrite  = NIL_RTSEMEVENT;
     589    AssertCompile(sizeof(hEvtWrite) == sizeof(pCritSect->Core.hEvtWrite));
     590
     591    SUPSEMEVENTMULTI hEvtRead  = (SUPSEMEVENTMULTI)pCritSect->Core.hEvtRead;
     592    pCritSect->Core.hEvtRead   = NIL_RTSEMEVENTMULTI;
     593    AssertCompile(sizeof(hEvtRead) == sizeof(pCritSect->Core.hEvtRead));
     594
     595    int rc1 = SUPSemEventClose(pVM->pSession, hEvtWrite);     AssertRC(rc1);
     596    int rc2 = SUPSemEventMultiClose(pVM->pSession, hEvtRead); AssertRC(rc2);
     597
     598    RTLockValidatorRecSharedDestroy(&pCritSect->Core.pValidatorRead);
     599    RTLockValidatorRecExclDestroy(&pCritSect->Core.pValidatorWrite);
     600
     601    pCritSect->pNext   = NULL;
     602    pCritSect->pvKey   = NULL;
     603    pCritSect->pVMR3   = NULL;
     604    pCritSect->pVMR0   = NIL_RTR0PTR;
     605    pCritSect->pVMRC   = NIL_RTRCPTR;
     606    RTStrFree((char *)pCritSect->pszName);
     607    pCritSect->pszName = NULL;
     608    if (!fFinal)
     609    {
     610        STAMR3Deregister(pVM, &pCritSect->StatContentionRZEnterExcl);
     611        STAMR3Deregister(pVM, &pCritSect->StatContentionRZLeaveExcl);
     612        STAMR3Deregister(pVM, &pCritSect->StatContentionRZEnterShared);
     613        STAMR3Deregister(pVM, &pCritSect->StatContentionRZLeaveShared);
     614        STAMR3Deregister(pVM, &pCritSect->StatRZEnterExcl);
     615        STAMR3Deregister(pVM, &pCritSect->StatRZEnterShared);
     616        STAMR3Deregister(pVM, &pCritSect->StatContentionR3EnterExcl);
     617        STAMR3Deregister(pVM, &pCritSect->StatContentionR3EnterShared);
     618        STAMR3Deregister(pVM, &pCritSect->StatR3EnterExcl);
     619        STAMR3Deregister(pVM, &pCritSect->StatR3EnterShared);
     620#ifdef VBOX_WITH_STATISTICS
     621        STAMR3Deregister(pVM, &pCritSect->StatWriteLocked);
     622#endif
     623    }
     624
     625    return RT_SUCCESS(rc1) ? rc2 : rc1;
     626}
     627
     628
     629/**
    351630 * Deletes all critical sections with a give initializer key.
    352631 *
     
    388667
    389668/**
    390  * Deletes all undeleted critical sections initialized by a given device.
     669 * Deletes all read/write critical sections with a give initializer key.
     670 *
     671 * @returns VBox status code.
     672 *          The entire list is processed on failure, so we'll only
     673 *          return the first error code. This shouldn't be a problem
     674 *          since errors really shouldn't happen here.
     675 * @param   pVM     Pointer to the VM.
     676 * @param   pvKey   The initializer key.
     677 */
     678static int pdmR3CritSectRwDeleteByKey(PVM pVM, void *pvKey)
     679{
     680    /*
     681     * Iterate the list and match key.
     682     */
     683    PUVM                pUVM  = pVM->pUVM;
     684    int                 rc    = VINF_SUCCESS;
     685    PPDMCRITSECTRWINT   pPrev = NULL;
     686    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     687    PPDMCRITSECTRWINT   pCur  = pUVM->pdm.s.pRwCritSects;
     688    while (pCur)
     689    {
     690        if (pCur->pvKey == pvKey)
     691        {
     692            int rc2 = pdmR3CritSectRwDeleteOne(pVM, pUVM, pCur, pPrev, false /* not final */);
     693            AssertRC(rc2);
     694            if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     695                rc = rc2;
     696        }
     697
     698        /* next */
     699        pPrev = pCur;
     700        pCur = pCur->pNext;
     701    }
     702    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     703    return rc;
     704}
     705
     706
     707/**
     708 * Deletes all undeleted critical sections (both types) initialized by a given
     709 * device.
    391710 *
    392711 * @returns VBox status code.
     
    394713 * @param   pDevIns     The device handle.
    395714 */
    396 int pdmR3CritSectDeleteDevice(PVM pVM, PPDMDEVINS pDevIns)
    397 {
    398     return pdmR3CritSectDeleteByKey(pVM, pDevIns);
    399 }
    400 
    401 
    402 /**
    403  * Deletes all undeleted critical sections initialized by a given driver.
     715int pdmR3CritSectBothDeleteDevice(PVM pVM, PPDMDEVINS pDevIns)
     716{
     717    int rc1 = pdmR3CritSectDeleteByKey(pVM, pDevIns);
     718    int rc2 = pdmR3CritSectRwDeleteByKey(pVM, pDevIns);
     719    return RT_SUCCESS(rc1) ? rc2 : rc1;
     720}
     721
     722
     723/**
     724 * Deletes all undeleted critical sections (both types) initialized by a given
     725 * driver.
    404726 *
    405727 * @returns VBox status code.
     
    407729 * @param   pDrvIns     The driver handle.
    408730 */
    409 int pdmR3CritSectDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns)
    410 {
    411     return pdmR3CritSectDeleteByKey(pVM, pDrvIns);
     731int pdmR3CritSectBothDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns)
     732{
     733    int rc1 = pdmR3CritSectDeleteByKey(pVM, pDrvIns);
     734    int rc2 = pdmR3CritSectRwDeleteByKey(pVM, pDrvIns);
     735    return RT_SUCCESS(rc1) ? rc2 : rc1;
    412736}
    413737
     
    453777
    454778/**
     779 * Deletes the read/write critical section.
     780 *
     781 * @returns VBox status code.
     782 * @param   pCritSect           The PDM read/write critical section to destroy.
     783 */
     784VMMR3DECL(int) PDMR3CritSectRwDelete(PPDMCRITSECTRW pCritSect)
     785{
     786    if (!PDMCritSectRwIsInitialized(pCritSect))
     787        return VINF_SUCCESS;
     788
     789    /*
     790     * Find and unlink it.
     791     */
     792    PVM                 pVM   = pCritSect->s.pVMR3;
     793    PUVM                pUVM  = pVM->pUVM;
     794    AssertReleaseReturn(pVM, VERR_PDM_CRITSECT_IPE);
     795    PPDMCRITSECTRWINT   pPrev = NULL;
     796    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     797    PPDMCRITSECTRWINT   pCur  = pUVM->pdm.s.pRwCritSects;
     798    while (pCur)
     799    {
     800        if (pCur == &pCritSect->s)
     801        {
     802            int rc = pdmR3CritSectRwDeleteOne(pVM, pUVM, pCur, pPrev, false /* not final */);
     803            RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     804            return rc;
     805        }
     806
     807        /* next */
     808        pPrev = pCur;
     809        pCur = pCur->pNext;
     810    }
     811    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     812    AssertReleaseMsgFailed(("pCritSect=%p wasn't found!\n", pCritSect));
     813    return VERR_PDM_CRITSECT_NOT_FOUND;
     814}
     815
     816
     817/**
    455818 * Gets the name of the critical section.
    456819 *
     
    464827    AssertPtrReturn(pCritSect, NULL);
    465828    AssertReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, NULL);
     829    return pCritSect->s.pszName;
     830}
     831
     832
     833/**
     834 * Gets the name of the read/write critical section.
     835 *
     836 *
     837 * @returns Pointer to the critical section name (read only) on success,
     838 *          NULL on failure (invalid critical section).
     839 * @param   pCritSect           The read/write critical section.
     840 */
     841VMMR3DECL(const char *) PDMR3CritSectRwName(PCPDMCRITSECTRW pCritSect)
     842{
     843    AssertPtrReturn(pCritSect, NULL);
     844    AssertReturn(pCritSect->s.Core.u32Magic == RTCRITSECTRW_MAGIC, NULL);
    466845    return pCritSect->s.pszName;
    467846}
     
    557936
    558937/**
    559  * Counts the critical sections owned by the calling thread, optionally
    560  * returning a comma separated list naming them.
     938 * PDMR3CritSectBothCountOwned worker.
     939 *
     940 * @param   pszName         The critical section name.
     941 * @param   ppszNames       Pointer to the pszNames variable.
     942 * @param   pcchLeft        Pointer to the cchLeft variable.
     943 * @param   fFirst          Whether this is the first name or not.
     944 */
     945static void pdmR3CritSectAppendNameToList(char const *pszName, char **ppszNames, size_t *pcchLeft, bool fFirst)
     946{
     947    size_t cchLeft = *pcchLeft;
     948    if (cchLeft)
     949    {
     950        char *pszNames = *ppszNames;
     951
     952        /* try add comma. */
     953        if (fFirst)
     954        {
     955            *pszNames++ = ',';
     956            if (--cchLeft)
     957            {
     958                *pszNames++ = ' ';
     959                cchLeft--;
     960            }
     961        }
     962
     963        /* try copy the name. */
     964        if (cchLeft)
     965        {
     966            size_t const cchName = strlen(pszName);
     967            if (cchName < cchLeft)
     968            {
     969                memcpy(pszNames, pszName, cchName);
     970                pszNames += cchName;
     971                cchLeft -= cchName;
     972            }
     973            else
     974            {
     975                if (cchLeft > 2)
     976                {
     977                    memcpy(pszNames, pszName, cchLeft - 2);
     978                    pszNames += cchLeft - 2;
     979                    cchLeft = 2;
     980                }
     981                while (cchLeft-- > 0)
     982                    *pszNames++ = '+';
     983            }
     984        }
     985        *pszNames = '\0';
     986
     987        *pcchLeft  = cchLeft;
     988        *ppszNames = pszNames;
     989    }
     990}
     991
     992
     993/**
     994 * Counts the critical sections (both type) owned by the calling thread,
     995 * optionally returning a comma separated list naming them.
     996 *
     997 * Read ownerships are not included in non-strict builds.
    561998 *
    562999 * This is for diagnostic purposes only.
     
    5831020     * Iterate the critical sections.
    5841021     */
     1022    uint32_t                cCritSects = 0;
     1023    RTNATIVETHREAD const    hNativeThread = RTThreadNativeSelf();
    5851024    /* This is unsafe, but wtf. */
    586     RTNATIVETHREAD const    hNativeThread = RTThreadNativeSelf();
    587     uint32_t                cCritSects = 0;
    5881025    for (PPDMCRITSECTINT pCur = pVM->pUVM->pdm.s.pCritSects;
    5891026         pCur;
     
    5941031        {
    5951032            cCritSects++;
    596 
    597             /*
    598              * Copy the name if there is space. Fun stuff.
    599              */
    600             if (cchLeft)
    601             {
    602                 /* try add comma. */
    603                 if (cCritSects != 1)
    604                 {
    605                     *pszNames++ = ',';
    606                     if (--cchLeft)
    607                     {
    608                         *pszNames++ = ' ';
    609                         cchLeft--;
    610                     }
    611                 }
    612 
    613                 /* try copy the name. */
    614                 if (cchLeft)
    615                 {
    616                     size_t const cchName = strlen(pCur->pszName);
    617                     if (cchName < cchLeft)
    618                     {
    619                         memcpy(pszNames, pCur->pszName, cchName);
    620                         pszNames += cchName;
    621                         cchLeft -= cchName;
    622                     }
    623                     else
    624                     {
    625                         if (cchLeft > 2)
    626                         {
    627                             memcpy(pszNames, pCur->pszName, cchLeft - 2);
    628                             pszNames += cchLeft - 2;
    629                             cchLeft = 2;
    630                         }
    631                         while (cchLeft-- > 0)
    632                             *pszNames++ = '+';
    633                     }
    634                 }
    635                 *pszNames = '\0';
    636             }
     1033            pdmR3CritSectAppendNameToList(pCur->pszName, &pszNames, &cchLeft, cCritSects == 1);
     1034        }
     1035    }
     1036
     1037    /* This is unsafe, but wtf. */
     1038    for (PPDMCRITSECTRWINT pCur = pVM->pUVM->pdm.s.pRwCritSects;
     1039         pCur;
     1040         pCur = pCur->pNext)
     1041    {
     1042        if (   pCur->Core.hNativeWriter == hNativeThread
     1043            || PDMCritSectRwIsReadOwner((PPDMCRITSECTRW)pCur, false /*fWannaHear*/) )
     1044        {
     1045            cCritSects++;
     1046            pdmR3CritSectAppendNameToList(pCur->pszName, &pszNames, &cchLeft, cCritSects == 1);
    6371047        }
    6381048    }
     
    6501060 * @param   pVM         Pointer to the VM.
    6511061 */
    652 VMMR3DECL(void) PDMR3CritSectLeaveAll(PVM pVM)
     1062VMMR3_INT_DECL(void) PDMR3CritSectLeaveAll(PVM pVM)
    6531063{
    6541064    RTNATIVETHREAD const hNativeSelf = RTThreadNativeSelf();
  • trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp

    r44358 r45152  
    962962
    963963        /* PDM critsects. */
    964         rc = pdmR3CritSectDeleteDriver(pVM, pCur);
     964        rc = pdmR3CritSectBothDeleteDriver(pVM, pCur);
    965965        AssertRC(rc);
    966966
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r45024 r45152  
    781781         * references to it are still working.
    782782         */
    783         PDMR3CritSectTerm(pVM);
     783        PDMR3CritSectBothTerm(pVM);
    784784
    785785        /*
     
    24402440        AssertRC(rc);
    24412441        SSMR3Term(pVM);
    2442         rc = PDMR3CritSectTerm(pVM);
     2442        rc = PDMR3CritSectBothTerm(pVM);
    24432443        AssertRC(rc);
    24442444        rc = MMR3Term(pVM);
  • trunk/src/VBox/VMM/VMMR3/VMM.cpp

    r44971 r45152  
    20982098     */
    20992099    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PDM_CRITSECT))
    2100         PDMCritSectFF(pVCpu);
     2100        PDMCritSectBothFF(pVCpu);
    21012101
    21022102    switch (pVCpu->vmm.s.enmCallRing3Operation)
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