- Timestamp:
- Mar 14, 2017 3:20:57 PM (8 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/VM.cpp
r65718 r66096 2551 2551 * wait for them to complete. 2552 2552 */ 2553 /* Signal them . */2553 /* Signal them - in reverse order since EMT(0) waits for the others. */ 2554 2554 ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true); 2555 2555 if (pUVM->pVM) 2556 2556 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) 2558 2559 { 2559 2560 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. */ 2566 2565 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) 2572 2586 { 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; 2584 2595 } 2585 2596 } 2586 2597 2587 2598 /* 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; 2592 2604 } 2593 2605 -
trunk/src/VBox/VMM/VMMR3/VMEmt.cpp
r63465 r66096 249 249 Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Rrc enmBefore=%d enmVMState=%d\n", 250 250 hThreadSelf, pUVM, rc, enmBefore, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_TERMINATED)); 251 PVM pVM; 251 252 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. */ 255 270 vmR3SetTerminated(pVM); 271 256 272 pUVM->pVM = NULL; 257 273 258 /** @todo SMP: This isn't 100% safe. We should wait for the other259 * threads to finish before destroy the VM. */260 274 int rc2 = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL); 261 275 AssertLogRelRC(rc2);
Note:
See TracChangeset
for help on using the changeset viewer.