/** * Deletes one critical section. * * @returns Return code from RTCritSectDelete. * * @param pVM Pointer to the VM. * @param pCritSect The critical section. * @param pPrev The previous critical section in the list. * @param fFinal Set if this is the final call and statistics shouldn't be deregistered. * * @remarks Caller must have entered the ListCritSect. */ static int pdmR3CritSectDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal) { /* * Assert free waiters and so on (c&p from RTCritSectDelete). */ Assert(pCritSect->Core.u32Magic == RTCRITSECT_MAGIC); Assert(pCritSect->Core.cNestings == 0); Assert(pCritSect->Core.cLockers == -1); Assert(pCritSect->Core.NativeThreadOwner == NIL_RTNATIVETHREAD); Assert(RTCritSectIsOwner(&pUVM->pdm.s.ListCritSect)); /* * Unlink it. */ if (pPrev) pPrev->pNext = pCritSect->pNext; else pUVM->pdm.s.pCritSects = pCritSect->pNext; /* * Delete it (parts taken from RTCritSectDelete). * In case someone is waiting we'll signal the semaphore cLockers + 1 times. */ ASMAtomicWriteU32(&pCritSect->Core.u32Magic, 0); SUPSEMEVENT hEvent = (SUPSEMEVENT)pCritSect->Core.EventSem; pCritSect->Core.EventSem = NIL_RTSEMEVENT; while (pCritSect->Core.cLockers-- >= 0) SUPSemEventSignal(pVM->pSession, hEvent); ASMAtomicWriteS32(&pCritSect->Core.cLockers, -1); int rc = SUPSemEventClose(pVM->pSession, hEvent); AssertRC(rc); RTLockValidatorRecExclDestroy(&pCritSect->Core.pValidatorRec); pCritSect->pNext = NULL; pCritSect->pvKey = NULL; pCritSect->pVMR3 = NULL; pCritSect->pVMR0 = NIL_RTR0PTR; pCritSect->pVMRC = NIL_RTRCPTR; RTStrFree((char *)pCritSect->pszName); pCritSect->pszName = NULL; if (!fFinal) { STAMR3Deregister(pVM, &pCritSect->StatContentionRZLock); STAMR3Deregister(pVM, &pCritSect->StatContentionRZUnlock); STAMR3Deregister(pVM, &pCritSect->StatContentionR3); #ifdef VBOX_WITH_STATISTICS STAMR3Deregister(pVM, &pCritSect->StatLocked); #endif } return rc; }
static int pdmacFileEpClose(PPDMASYNCCOMPLETIONENDPOINT pEndpoint) { int rc = VINF_SUCCESS; PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint; PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->pEpClass; /* Make sure that all tasks finished for this endpoint. */ rc = pdmacFileAioMgrCloseEndpoint(pEpFile->pAioMgr, pEpFile); AssertRC(rc); /* * If the async I/O manager is in failsafe mode this is the only endpoint * he processes and thus can be destroyed now. */ if (pEpFile->pAioMgr->enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE) pdmacFileAioMgrDestroy(pEpClassFile, pEpFile->pAioMgr); /* Free cached tasks. */ PPDMACTASKFILE pTask = pEpFile->pTasksFreeHead; while (pTask) { PPDMACTASKFILE pTaskFree = pTask; pTask = pTask->pNext; MMR3HeapFree(pTaskFree); } /* Destroy the locked ranges tree now. */ RTAvlrFileOffsetDestroy(pEpFile->AioMgr.pTreeRangesLocked, pdmacFileEpRangesLockedDestroy, NULL); RTFileClose(pEpFile->hFile); #ifdef VBOX_WITH_STATISTICS STAMR3Deregister(pEpClassFile->Core.pVM, &pEpFile->StatRead); STAMR3Deregister(pEpClassFile->Core.pVM, &pEpFile->StatWrite); #endif return VINF_SUCCESS; }
/** * Destroy a queue. * * @returns VBox status code. * @param pQueue Queue to destroy. * @thread Emulation thread only. */ VMMR3_INT_DECL(int) PDMR3QueueDestroy(PPDMQUEUE pQueue) { LogFlow(("PDMR3QueueDestroy: pQueue=%p\n", pQueue)); /* * Validate input. */ if (!pQueue) return VERR_INVALID_PARAMETER; Assert(pQueue && pQueue->pVMR3); PVM pVM = pQueue->pVMR3; PUVM pUVM = pVM->pUVM; pdmLock(pVM); /* * Unlink it. */ if (pQueue->pTimer) { if (pUVM->pdm.s.pQueuesTimer != pQueue) { PPDMQUEUE pCur = pUVM->pdm.s.pQueuesTimer; while (pCur) { if (pCur->pNext == pQueue) { pCur->pNext = pQueue->pNext; break; } pCur = pCur->pNext; } AssertMsg(pCur, ("Didn't find the queue!\n")); } else pUVM->pdm.s.pQueuesTimer = pQueue->pNext; } else { if (pUVM->pdm.s.pQueuesForced != pQueue) { PPDMQUEUE pCur = pUVM->pdm.s.pQueuesForced; while (pCur) { if (pCur->pNext == pQueue) { pCur->pNext = pQueue->pNext; break; } pCur = pCur->pNext; } AssertMsg(pCur, ("Didn't find the queue!\n")); } else pUVM->pdm.s.pQueuesForced = pQueue->pNext; } pQueue->pNext = NULL; pQueue->pVMR3 = NULL; pdmUnlock(pVM); /* * Deregister statistics. */ STAMR3Deregister(pVM, &pQueue->cbItem); STAMR3Deregister(pVM, &pQueue->cbItem); STAMR3Deregister(pVM, &pQueue->StatAllocFailures); STAMR3Deregister(pVM, &pQueue->StatInsert); STAMR3Deregister(pVM, &pQueue->StatFlush); STAMR3Deregister(pVM, &pQueue->StatFlushLeftovers); #ifdef VBOX_WITH_STATISTICS STAMR3Deregister(pVM, &pQueue->StatFlushPrf); STAMR3Deregister(pVM, (void *)&pQueue->cStatPending); #endif /* * Destroy the timer and free it. */ if (pQueue->pTimer) { TMR3TimerDestroy(pQueue->pTimer); pQueue->pTimer = NULL; } if (pQueue->pVMRC) { pQueue->pVMRC = NIL_RTRCPTR; pQueue->pVMR0 = NIL_RTR0PTR; MMHyperFree(pVM, pQueue); } else MMR3HeapFree(pQueue); return VINF_SUCCESS; }