VirtualBox

Changeset 66096 in vbox for trunk


Ignore:
Timestamp:
Mar 14, 2017 3:20:57 PM (8 years ago)
Author:
vboxsync
Message:

VMM: EMT(0) must wait on any other EMTs before destroying the VM or we may get errors from the wait code (vmR3HaltGlobal1Wait).

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

Legend:

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

    r65718 r66096  
    25512551     * wait for them to complete.
    25522552     */
    2553     /* Signal them. */
     2553    /* Signal them - in reverse order since EMT(0) waits for the others. */
    25542554    ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    25552555    if (pUVM->pVM)
    25562556        VM_FF_SET(pUVM->pVM, VM_FF_CHECK_VM_STATE); /* Can't hurt... */
    2557     for (VMCPUID i = 0; i < pUVM->cCpus; i++)
     2557    VMCPUID iCpu = pUVM->cCpus;
     2558    while (iCpu-- > 0)
    25582559    {
    25592560        VMR3NotifyGlobalFFU(pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
    2560         RTSemEventSignal(pUVM->aCpus[i].vm.s.EventSemWait);
    2561     }
    2562 
    2563     /* Wait for them. */
    2564     uint64_t    NanoTS = RTTimeNanoTS();
    2565     RTTHREAD    hSelf  = RTThreadSelf();
     2561        RTSemEventSignal(pUVM->aCpus[iCpu].vm.s.EventSemWait);
     2562    }
     2563
     2564    /* Wait for EMT(0), it in turn waits for the rest. */
    25662565    ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    2567     for (VMCPUID i = 0; i < pUVM->cCpus; i++)
    2568     {
    2569         RTTHREAD hThread = pUVM->aCpus[i].vm.s.ThreadEMT;
    2570         if (    hThread != NIL_RTTHREAD
    2571             &&  hThread != hSelf)
     2566
     2567    RTTHREAD const hSelf = RTThreadSelf();
     2568    RTTHREAD hThread = pUVM->aCpus[0].vm.s.ThreadEMT;
     2569    if (   hThread != NIL_RTTHREAD
     2570        && hThread != hSelf)
     2571    {
     2572        int rc2 = RTThreadWait(hThread, RT_MAX(cMilliesEMTWait, 2000), NULL);
     2573        if (rc2 == VERR_TIMEOUT) /* avoid the assertion when debugging. */
     2574            rc2 = RTThreadWait(hThread, 1000, NULL);
     2575        AssertLogRelMsgRC(rc2, ("iCpu=0 rc=%Rrc\n", rc2));
     2576        if (RT_SUCCESS(rc2))
     2577            pUVM->aCpus[0].vm.s.ThreadEMT = NIL_RTTHREAD;
     2578    }
     2579
     2580    /* Just in case we're in a weird failure situation w/o EMT(0) to do the
     2581       waiting, wait the other EMTs too. */
     2582    for (iCpu = 1; iCpu < pUVM->cCpus; iCpu++)
     2583    {
     2584        ASMAtomicXchgHandle(&pUVM->aCpus[iCpu].vm.s.ThreadEMT, NIL_RTTHREAD, &hThread);
     2585        if (hThread != NIL_RTTHREAD)
    25722586        {
    2573             uint64_t cMilliesElapsed = (RTTimeNanoTS() - NanoTS) / 1000000;
    2574             int rc2 = RTThreadWait(hThread,
    2575                                    cMilliesElapsed < cMilliesEMTWait
    2576                                    ? RT_MAX(cMilliesEMTWait - cMilliesElapsed, 2000)
    2577                                    : 2000,
    2578                                    NULL);
    2579             if (rc2 == VERR_TIMEOUT) /* avoid the assertion when debugging. */
    2580                 rc2 = RTThreadWait(hThread, 1000, NULL);
    2581             AssertLogRelMsgRC(rc2, ("i=%u rc=%Rrc\n", i, rc2));
    2582             if (RT_SUCCESS(rc2))
    2583                 pUVM->aCpus[0].vm.s.ThreadEMT = NIL_RTTHREAD;
     2587            if (hThread != hSelf)
     2588            {
     2589                int rc2 = RTThreadWait(hThread, 250 /*ms*/, NULL);
     2590                AssertLogRelMsgRC(rc2, ("iCpu=%u rc=%Rrc\n", iCpu, rc2));
     2591                if (RT_SUCCESS(rc2))
     2592                    continue;
     2593            }
     2594            pUVM->aCpus[iCpu].vm.s.ThreadEMT = hThread;
    25842595        }
    25852596    }
    25862597
    25872598    /* Cleanup the semaphores. */
    2588     for (VMCPUID i = 0; i < pUVM->cCpus; i++)
    2589     {
    2590         RTSemEventDestroy(pUVM->aCpus[i].vm.s.EventSemWait);
    2591         pUVM->aCpus[i].vm.s.EventSemWait = NIL_RTSEMEVENT;
     2599    iCpu = pUVM->cCpus;
     2600    while (iCpu-- > 0)
     2601    {
     2602        RTSemEventDestroy(pUVM->aCpus[iCpu].vm.s.EventSemWait);
     2603        pUVM->aCpus[iCpu].vm.s.EventSemWait = NIL_RTSEMEVENT;
    25922604    }
    25932605
  • trunk/src/VBox/VMM/VMMR3/VMEmt.cpp

    r63465 r66096  
    249249    Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Rrc enmBefore=%d enmVMState=%d\n",
    250250         hThreadSelf, pUVM, rc, enmBefore, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_TERMINATED));
     251    PVM pVM;
    251252    if (   idCpu == 0
    252         && pUVM->pVM)
    253     {
    254         PVM pVM = pUVM->pVM;
     253        && (pVM = pUVM->pVM) != NULL)
     254    {
     255        /* Wait for any other EMTs to terminate before we destroy the VM (see vmR3DestroyVM). */
     256        for (VMCPUID iCpu = 1; iCpu < pUVM->cCpus; iCpu++)
     257        {
     258            RTTHREAD hThread;
     259            ASMAtomicXchgHandle(&pUVM->aCpus[iCpu].vm.s.ThreadEMT, NIL_RTTHREAD, &hThread);
     260            if (hThread != NIL_RTTHREAD)
     261            {
     262                int rc2 = RTThreadWait(hThread, 5 * RT_NS_1SEC, NULL);
     263                AssertLogRelMsgRC(rc2, ("iCpu=%u rc=%Rrc\n", iCpu, rc2));
     264                if (RT_FAILURE(rc2))
     265                    pUVM->aCpus[iCpu].vm.s.ThreadEMT = hThread;
     266            }
     267        }
     268
     269        /* Switch to the terminated state, clearing the VM pointer and finally destroy the VM. */
    255270        vmR3SetTerminated(pVM);
     271
    256272        pUVM->pVM = NULL;
    257273
    258         /** @todo SMP: This isn't 100% safe. We should wait for the other
    259          *        threads to finish before destroy the VM. */
    260274        int rc2 = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
    261275        AssertLogRelRC(rc2);
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