RTDECL(int) RTReqQueueDestroy(RTREQQUEUE hQueue) { /* * Check input. */ if (hQueue == NIL_RTREQQUEUE) return VINF_SUCCESS; PRTREQQUEUEINT pQueue = hQueue; AssertPtrReturn(pQueue, VERR_INVALID_HANDLE); AssertReturn(ASMAtomicCmpXchgU32(&pQueue->u32Magic, RTREQQUEUE_MAGIC_DEAD, RTREQQUEUE_MAGIC), VERR_INVALID_HANDLE); RTSemEventDestroy(pQueue->EventSem); pQueue->EventSem = NIL_RTSEMEVENT; for (unsigned i = 0; i < RT_ELEMENTS(pQueue->apReqFree); i++) { PRTREQ pReq = (PRTREQ)ASMAtomicXchgPtr((void **)&pQueue->apReqFree[i], NULL); while (pReq) { PRTREQ pNext = pReq->pNext; rtReqFreeIt(pReq); pReq = pNext; } } RTMemFree(pQueue); return VINF_SUCCESS; }
RTDECL(uint32_t) RTReqRelease(PRTREQ hReq) { /* * Ignore NULL and validate the request. */ if (!hReq) return 0; PRTREQINT pReq = hReq; AssertPtrReturn(pReq, UINT32_MAX); AssertReturn(pReq->u32Magic == RTREQ_MAGIC, UINT32_MAX); /* * Drop a reference, recycle the request when we reach 0. */ uint32_t cRefs = ASMAtomicDecU32(&pReq->cRefs); if (cRefs == 0) { /* * Check packet state. */ switch (pReq->enmState) { case RTREQSTATE_ALLOCATED: case RTREQSTATE_COMPLETED: break; default: AssertMsgFailed(("Invalid state %d!\n", pReq->enmState)); return 0; } /* * Make it a free packet and put it into one of the free packet lists. */ pReq->enmState = RTREQSTATE_FREE; pReq->iStatusX = VERR_RT_REQUEST_STATUS_FREED; pReq->enmType = RTREQTYPE_INVALID; bool fRecycled; if (pReq->fPoolOrQueue) fRecycled = rtReqPoolRecycle(pReq->uOwner.hPool, pReq); else fRecycled = rtReqQueueRecycle(pReq->uOwner.hQueue, pReq); if (!fRecycled) rtReqFreeIt(pReq); } return cRefs; }
/** * Re-initializes a request when it's being recycled. * * @returns IRPT status code, the request is freed on failure. * @param pReq The request. * @param enmType The request type. */ DECLHIDDEN(int) rtReqReInit(PRTREQINT pReq, RTREQTYPE enmType) { Assert(pReq->u32Magic == RTREQ_MAGIC); Assert(pReq->enmType == RTREQTYPE_INVALID); Assert(pReq->enmState == RTREQSTATE_FREE); Assert(pReq->cRefs == 0); /* * Make sure the event sem is not signaled. */ if (!pReq->fEventSemClear) { int rc = RTSemEventWait(pReq->EventSem, 0); if (rc != VINF_SUCCESS && rc != VERR_TIMEOUT) { /* * This shall not happen, but if it does we'll just destroy * the semaphore and create a new one. */ AssertMsgFailed(("rc=%Rrc from RTSemEventWait(%#x).\n", rc, pReq->EventSem)); RTSemEventDestroy(pReq->EventSem); rc = RTSemEventCreate(&pReq->EventSem); if (RT_FAILURE(rc)) { AssertRC(rc); pReq->EventSem = NIL_RTSEMEVENT; rtReqFreeIt(pReq); return rc; } } pReq->fEventSemClear = true; } else Assert(RTSemEventWait(pReq->EventSem, 0) == VERR_TIMEOUT); /* * Initialize the packet and return it. */ ASMAtomicWriteNullPtr(&pReq->pNext); pReq->iStatusX = VERR_RT_REQUEST_STATUS_STILL_PENDING; pReq->enmState = RTREQSTATE_ALLOCATED; pReq->fFlags = RTREQFLAGS_IPRT_STATUS; pReq->enmType = enmType; pReq->cRefs = 1; return VINF_SUCCESS; }