/** * Suspend all running threads. * * This is called by PDMR3Suspend() and PDMR3PowerOff() after all the devices * and drivers have been notified about the suspend / power off. * * @return VBox status code. * @param pVM Pointer to the VM. */ int pdmR3ThreadSuspendAll(PVM pVM) { PUVM pUVM = pVM->pUVM; RTCritSectEnter(&pUVM->pdm.s.ListCritSect); /* This may cause deadlocks later... */ for (PPDMTHREAD pThread = pUVM->pdm.s.pThreads; pThread; pThread = pThread->Internal.s.pNext) switch (pThread->enmState) { case PDMTHREADSTATE_RUNNING: { int rc = PDMR3ThreadSuspend(pThread); AssertRCReturn(rc, rc); break; } /* suspend -> power off; voluntary suspend. */ case PDMTHREADSTATE_SUSPENDED: break; default: AssertMsgFailed(("pThread=%p enmState=%d\n", pThread, pThread->enmState)); break; } RTCritSectLeave(&pUVM->pdm.s.ListCritSect); return VINF_SUCCESS; }
/** * Callback employed by drvscsiSuspend and drvscsiPowerOff. * * @returns true if we've quiesced, false if we're still working. * @param pDrvIns The driver instance. */ static DECLCALLBACK(bool) drvscsiIsAsyncSuspendOrPowerOffDone(PPDMDRVINS pDrvIns) { PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); if (pThis->pDrvBlockAsync) { if (pThis->StatIoDepth > 0) return false; else return true; } else { if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/)) return false; ASMAtomicWriteBool(&pThis->fDummySignal, false); PDMR3ThreadSuspend(pThis->pAsyncIOThread); return true; } }