VirtualBox

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


Ignore:
Timestamp:
Dec 15, 2015 12:42:54 PM (9 years ago)
Author:
vboxsync
Message:

VMM: Recursive EMT rendezvous fixes, adding support for recursion from within VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE callbacks too.

File:
1 edited

Legend:

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

    r59126 r59132  
    17291729            if (!fIsCaller)
    17301730            {
    1731                 rc = RTSemEventMultiWait(pVM->vmm.s.hEvtMulRendezvousDone, RT_INDEFINITE_WAIT);
    1732                 AssertLogRelRC(rc);
    1733                 Assert(!pVM->vmm.s.fRendezvousRecursion);
     1731                for (;;)
     1732                {
     1733                    rc = RTSemEventMultiWait(pVM->vmm.s.hEvtMulRendezvousDone, RT_INDEFINITE_WAIT);
     1734                    AssertLogRelRC(rc);
     1735                    if (!pVM->vmm.s.fRendezvousRecursion)
     1736                        break;
     1737                    rcStrictRecursion = vmmR3EmtRendezvousCommonRecursion(pVM, pVCpu, rcStrictRecursion);
     1738                }
    17341739
    17351740                return vmmR3EmtRendezvousNonCallerReturn(pVM, rcStrictRecursion);
     
    17641769                rc = RTSemEventSignal(pVM->vmm.s.pahEvtRendezvousEnterOrdered[iFirst]);
    17651770                AssertLogRelRC(rc);
    1766                 rc = RTSemEventWait(pVM->vmm.s.pahEvtRendezvousEnterOrdered[pVCpu->idCpu], RT_INDEFINITE_WAIT);
    1767                 AssertLogRelRC(rc);
     1771                for (;;)
     1772                {
     1773                    rc = RTSemEventWait(pVM->vmm.s.pahEvtRendezvousEnterOrdered[pVCpu->idCpu], RT_INDEFINITE_WAIT);
     1774                    AssertLogRelRC(rc);
     1775                    if (!pVM->vmm.s.fRendezvousRecursion)
     1776                        break;
     1777                    rcStrictRecursion = vmmR3EmtRendezvousCommonRecursion(pVM, pVCpu, rcStrictRecursion);
     1778                }
    17681779            }
    17691780        }
     
    19241935    AssertReturn(   (fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING
    19251936                 || (fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING
    1926                  || (fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE,
     1937                 || (fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE
     1938                 || (fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE,
    19271939                 VERR_INTERNAL_ERROR);
    19281940    AssertReturn(pVM->vmm.s.cRendezvousEmtsEntered == pVM->cCpus, VERR_INTERNAL_ERROR_2);
     
    19451957     */
    19461958    ASMAtomicWriteU32(&pVM->vmm.s.cRendezvousEmtsRecursingPush, 0);
    1947     ASMAtomicWriteU32(&pVM->vmm.s.cRendezvousEmtsRecursingPop, 0);
    19481959    ASMAtomicWriteBool(&pVM->vmm.s.fRendezvousRecursion, true);
    19491960
    19501961    uint32_t cLeft = pVM->cCpus - (cParentDone + 1U);
    1951     if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE)
     1962    if ((fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE)
    19521963        while (cLeft-- > 0)
    19531964        {
     
    19551966            AssertLogRelRC(rc);
    19561967        }
    1957     else if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING)
     1968    else if ((fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING)
    19581969    {
    19591970        Assert(cLeft == pVM->cCpus - (pVCpu->idCpu + 1U));
     
    19641975        }
    19651976    }
    1966     else if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING)
     1977    else if ((fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING)
    19671978    {
    19681979        Assert(cLeft == pVCpu->idCpu);
    1969         for (VMCPUID iCpu = pVCpu->idCpu; iCpu > pVM->cCpus; iCpu--)
     1980        for (VMCPUID iCpu = pVCpu->idCpu; iCpu > 0; iCpu--)
    19701981        {
    19711982            rc = RTSemEventSignal(pVM->vmm.s.pahEvtRendezvousEnterOrdered[iCpu - 1U]);
     
    19741985    }
    19751986    else
    1976         AssertLogRelFailedReturn(VERR_INTERNAL_ERROR_4);
     1987        AssertLogRelReturn((fParentFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE,
     1988                           VERR_INTERNAL_ERROR_4);
    19771989
    19781990    rc = RTSemEventMultiSignal(pVM->vmm.s.hEvtMulRendezvousDone);
     
    20692081     * Usher the other EMTs back to their parent recursion routine, waiting
    20702082     * for them to all get there before we return (makes sure they've been
    2071      * scheduled and are in position again - paranoia, shouldn't be needed).
    2072      */
    2073     rc = RTSemEventMultiSignal(pVM->vmm.s.hEvtMulRendezvousRecursionPush);
     2083     * scheduled and are past the pop event sem, see below).
     2084     */
     2085    ASMAtomicWriteU32(&pVM->vmm.s.cRendezvousEmtsRecursingPop, 0);
     2086    rc = RTSemEventMultiSignal(pVM->vmm.s.hEvtMulRendezvousRecursionPop);
    20742087    AssertLogRelRC(rc);
    20752088
     
    20792092        AssertLogRelRC(rc);
    20802093    }
     2094
     2095    /*
     2096     * We must reset the pop semaphore on the way out (doing the pop caller too,
     2097     * just in case).  The parent may be another recursion.
     2098     */
     2099    rc = RTSemEventMultiReset(pVM->vmm.s.hEvtMulRendezvousRecursionPop);    AssertLogRelRC(rc);
     2100    rc = vmmR3HlpResetEvent(pVM->vmm.s.hEvtRendezvousRecursionPopCaller);   AssertLogRelMsg(rc == VERR_TIMEOUT, ("%Rrc\n", rc));
    20812101
    20822102    ASMAtomicDecU32(&pVM->vmm.s.cRendezvousRecursions);
     
    21352155         * Shortcut for the single EMT case.
    21362156         */
    2137         AssertLogRelReturn(!pVCpu->vmm.s.fInRendezvous, VERR_DEADLOCK);
    2138         pVCpu->vmm.s.fInRendezvous = true;
    2139         rcStrict = pfnRendezvous(pVM, pVCpu, pvUser);
    2140         pVCpu->vmm.s.fInRendezvous = false;
     2157        if (!pVCpu->vmm.s.fInRendezvous)
     2158        {
     2159            pVCpu->vmm.s.fInRendezvous  = true;
     2160            pVM->vmm.s.fRendezvousFlags = fFlags;
     2161            rcStrict = pfnRendezvous(pVM, pVCpu, pvUser);
     2162            pVCpu->vmm.s.fInRendezvous  = false;
     2163        }
     2164        else
     2165        {
     2166            /* Recursion. Do the same checks as in the SMP case. */
     2167            uint32_t fType = pVM->vmm.s.fRendezvousFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK;
     2168            AssertLogRelReturn(   !pVCpu->vmm.s.fInRendezvous
     2169                               || fType == VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING
     2170                               || fType == VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING
     2171                               || fType == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE
     2172                               || fType == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE
     2173                               , VERR_DEADLOCK);
     2174
     2175            AssertLogRelReturn(pVM->vmm.s.cRendezvousRecursions < 3, VERR_DEADLOCK);
     2176            pVM->vmm.s.cRendezvousRecursions++;
     2177            uint32_t const fParentFlags = pVM->vmm.s.fRendezvousFlags;
     2178            pVM->vmm.s.fRendezvousFlags = fFlags;
     2179
     2180            rcStrict = pfnRendezvous(pVM, pVCpu, pvUser);
     2181
     2182            pVM->vmm.s.fRendezvousFlags = fParentFlags;
     2183            pVM->vmm.s.cRendezvousRecursions--;
     2184        }
    21412185    }
    21422186    else
     
    21552199                    || (pVM->vmm.s.fRendezvousFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING
    21562200                    || (pVM->vmm.s.fRendezvousFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE
     2201                    || (pVM->vmm.s.fRendezvousFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE
    21572202                       ))
    21582203                return VBOXSTRICTRC_TODO(vmmR3EmtRendezvousRecursive(pVM, pVCpu, fFlags, pfnRendezvous, pvUser));
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