VirtualBox

Changeset 90672 in vbox for trunk


Ignore:
Timestamp:
Aug 12, 2021 9:27:26 PM (3 years ago)
Author:
vboxsync
Message:

VMM/PDMCritSectRwEnterShared: Some more code refactoring. Added StatContentionR3LeaveExcl. bugref:6695

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

Legend:

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

    r90671 r90672  
    208208
    209209/**
     210 * Worker for pdmCritSectRwEnterSharedContended that decrements both read counts
     211 * and returns @a rc.
     212 */
     213DECL_FORCE_INLINE(int) pdmCritSectRwEnterSharedBailOut(PPDMCRITSECTRW pThis, int rc)
     214{
     215    for (;;)
     216    {
     217        uint64_t       u64State    = PDMCRITSECTRW_READ_STATE(&pThis->s.Core.u.s.u64State);
     218        uint64_t const u64OldState = u64State;
     219        uint64_t       c           = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
     220        AssertReturn(c > 0, pdmCritSectRwCorrupted(pThis, "Invalid read count on bailout"));
     221        c--;
     222        uint64_t       cWait       = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
     223        AssertReturn(cWait > 0, pdmCritSectRwCorrupted(pThis, "Invalid waiting read count on bailout"));
     224        cWait--;
     225        u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
     226        u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
     227        if (ASMAtomicCmpXchgU64(&pThis->s.Core.u.s.u64State, u64State, u64OldState))
     228            return rc;
     229
     230        ASMNopPause();
     231        AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
     232    }
     233}
     234
     235
     236/**
    210237 * Worker for pdmCritSectRwEnterShared returning with read-ownership of the CS.
    211238 */
     
    240267# endif
    241268
    242     uint64_t u64State;
    243     uint64_t u64OldState;
     269    /*
     270     * Wait for the direction to switch.
     271     */
    244272    for (uint32_t iLoop = 0; ; iLoop++)
    245273    {
     
    249277        rc = RTLockValidatorRecSharedCheckBlocking(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos, true,
    250278                                                   RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_READ, false);
    251         if (RT_SUCCESS(rc))
     279        if (RT_FAILURE(rc))
     280            return pdmCritSectRwEnterSharedBailOut(pThis, rc);
    252281#  else
    253282        RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_READ, false);
    254283#  endif
    255284# endif
     285        for (;;)
    256286        {
     287            rc = SUPSemEventMultiWaitNoResume(pVM->pSession,
     288                                              (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead,
     289                                              RT_INDEFINITE_WAIT);
     290            if (   rc != VERR_INTERRUPTED
     291                || pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
     292                break;
     293# ifdef IN_RING0
     294            pdmR0CritSectRwYieldToRing3(pVM);
     295# endif
     296        }
     297# ifdef IN_RING3
     298        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
     299# endif
     300        if (RT_LIKELY(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC))
     301        { /* likely */ }
     302        else
     303            return VERR_SEM_DESTROYED;
     304        if (RT_SUCCESS(rc))
     305        { /* likely */ }
     306        else
     307            return pdmCritSectRwEnterSharedBailOut(pThis, rc);
     308
     309        /*
     310         * Check the direction.
     311         */
     312        Assert(pThis->s.Core.fNeedReset);
     313        uint64_t u64State = PDMCRITSECTRW_READ_STATE(&pThis->s.Core.u.s.u64State);
     314        if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
     315        {
     316            /*
     317             * Decrement the wait count and maybe reset the semaphore (if we're last).
     318             */
    257319            for (;;)
    258320            {
    259                 rc = SUPSemEventMultiWaitNoResume(pVM->pSession,
    260                                                   (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead,
    261                                                   RT_INDEFINITE_WAIT);
    262                 if (   rc != VERR_INTERRUPTED
    263                     || pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    264                     break;
    265 # ifdef IN_RING0
    266                 pdmR0CritSectRwYieldToRing3(pVM);
    267 # endif
    268             }
    269 # ifdef IN_RING3
    270             RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
    271 # endif
    272             if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    273                 return VERR_SEM_DESTROYED;
    274         }
    275         if (RT_FAILURE(rc))
    276         {
    277             /* Decrement the counts and return the error. */
    278             for (;;)
    279             {
    280                 u64OldState = u64State = PDMCRITSECTRW_READ_STATE(&pThis->s.Core.u.s.u64State);
    281                 uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
    282                 AssertReturn(c > 0, pdmCritSectRwCorrupted(pThis, "Invalid read count on bailout"));
    283                 c--;
    284                 uint64_t cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
    285                 AssertReturn(cWait > 0, pdmCritSectRwCorrupted(pThis, "Invalid waiting read count on bailout"));
     321                uint64_t const u64OldState = u64State;
     322                uint64_t       cWait       = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
     323                AssertReturn(cWait > 0, pdmCritSectRwCorrupted(pThis, "Invalid waiting read count"));
     324                AssertReturn((u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT > 0,
     325                             pdmCritSectRwCorrupted(pThis, "Invalid read count"));
    286326                cWait--;
    287                 u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
    288                 u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
     327                u64State &= ~RTCSRW_WAIT_CNT_RD_MASK;
     328                u64State |= cWait << RTCSRW_WAIT_CNT_RD_SHIFT;
     329
    289330                if (ASMAtomicCmpXchgU64(&pThis->s.Core.u.s.u64State, u64State, u64OldState))
    290                     break;
     331                {
     332                    if (cWait == 0)
     333                    {
     334                        if (ASMAtomicXchgBool(&pThis->s.Core.fNeedReset, false))
     335                        {
     336                            rc = SUPSemEventMultiReset(pVM->pSession, (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead);
     337                            AssertRCReturn(rc, rc);
     338                        }
     339                    }
     340                    return pdmCritSectRwEnterSharedGotIt(pThis, pSrcPos, fNoVal, hThreadSelf);
     341                }
    291342
    292343                ASMNopPause();
    293344                AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
     345                ASMNopPause();
     346
     347                u64State = PDMCRITSECTRW_READ_STATE(&pThis->s.Core.u.s.u64State);
    294348            }
    295             return rc;
     349            /* not reached */
    296350        }
    297351
    298         Assert(pThis->s.Core.fNeedReset);
    299         u64State = PDMCRITSECTRW_READ_STATE(&pThis->s.Core.u.s.u64State);
    300         if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
    301             break;
    302352        AssertMsg(iLoop < 1, ("%u\n", iLoop));
    303     }
    304 
    305     /* Decrement the wait count and maybe reset the semaphore (if we're last). */
    306     for (;;)
    307     {
    308         u64OldState = u64State;
    309 
    310         uint64_t cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
    311         AssertReturn(cWait > 0, pdmCritSectRwCorrupted(pThis, "Invalid waiting read count"));
    312         cWait--;
    313         u64State &= ~RTCSRW_WAIT_CNT_RD_MASK;
    314         u64State |= cWait << RTCSRW_WAIT_CNT_RD_SHIFT;
    315 
    316         if (ASMAtomicCmpXchgU64(&pThis->s.Core.u.s.u64State, u64State, u64OldState))
    317         {
    318             if (cWait == 0)
    319             {
    320                 if (ASMAtomicXchgBool(&pThis->s.Core.fNeedReset, false))
    321                 {
    322                     int rc = SUPSemEventMultiReset(pVM->pSession, (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead);
    323                     AssertRCReturn(rc, rc);
    324                 }
    325             }
    326             return pdmCritSectRwEnterSharedGotIt(pThis, pSrcPos, fNoVal, hThreadSelf);
    327         }
    328 
    329         ASMNopPause();
    330         AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
    331         ASMNopPause();
    332 
    333         u64State = PDMCRITSECTRW_READ_STATE(&pThis->s.Core.u.s.u64State);
     353        RTThreadYield();
    334354    }
    335355
     
    15911611                if (ASMAtomicCmpXchgU64(&pThis->s.Core.u.s.u64State, u64State, u64OldState))
    15921612                {
     1613                    STAM_REL_COUNTER_INC(&pThis->s.CTX_MID_Z(StatContention,LeaveExcl));
    15931614                    int rc;
    15941615                    if (c == 0)
     
    16231644                    Assert(!pThis->s.Core.fNeedReset);
    16241645                    ASMAtomicWriteBool(&pThis->s.Core.fNeedReset, true);
     1646                    STAM_REL_COUNTER_INC(&pThis->s.CTX_MID_Z(StatContention,LeaveExcl));
    16251647
    16261648                    int rc;
  • trunk/src/VBox/VMM/VMMR3/PDMCritSect.cpp

    r90639 r90672  
    310310                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLeaveShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZLeaveShared", pCritSect->pszName);
    311311                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3EnterExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3EnterExcl", pCritSect->pszName);
     312                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3LeaveExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3LeaveExcl", pCritSect->pszName);
    312313                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3EnterShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3EnterShared", pCritSect->pszName);
    313314                    STAMR3RegisterF(pVM, &pCritSect->StatRZEnterExcl,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/RZEnterExcl", pCritSect->pszName);
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r90637 r90672  
    503503    /** R3 write lock contention. */
    504504    STAMCOUNTER                         StatContentionR3EnterExcl;
     505    /** R3 write unlock contention. */
     506    STAMCOUNTER                         StatContentionR3LeaveExcl;
    505507    /** R3 read lock contention. */
    506508    STAMCOUNTER                         StatContentionR3EnterShared;
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