/** * Unblocks a thread. * * This function is paired with rtThreadBlocking. * * @param hThread The current thread. * @param enmCurState The current state, used to check for nested blocking. * The new state will be running. */ RTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState) { PRTTHREADINT pThread = hThread; if (pThread != NIL_RTTHREAD) { Assert(pThread == RTThreadSelf()); ASMAtomicWriteBool(&pThread->fReallySleeping, false); RTTHREADSTATE enmActualState = rtThreadGetState(pThread); if (enmActualState == enmCurState) { rtThreadSetState(pThread, RTTHREADSTATE_RUNNING); if ( pThread->LockValidator.pRec && pThread->LockValidator.enmRecState == enmCurState) ASMAtomicWriteNullPtr(&pThread->LockValidator.pRec); } /* This is a bit ugly... :-/ */ else if ( ( enmActualState == RTTHREADSTATE_TERMINATED || enmActualState == RTTHREADSTATE_INITIALIZING) && pThread->LockValidator.pRec) ASMAtomicWriteNullPtr(&pThread->LockValidator.pRec); Assert( pThread->LockValidator.pRec == NULL || RTTHREAD_IS_SLEEPING(enmActualState)); } }
/** * Thread enumerator - clears a TLS entry. * * @returns 0. * @param pNode The thread node. * @param pvUser The TLS index. */ static DECLCALLBACK(int) rtThreadClearTlsEntryCallback(PAVLPVNODECORE pNode, void *pvUser) { PRTTHREADINT pThread = (PRTTHREADINT)pNode; RTTLS iTls = (RTTLS)(uintptr_t)pvUser; ASMAtomicWriteNullPtr(&pThread->apvTlsEntries[iTls]); return 0; }
/** * Removes a request from the active list. * * @returns nothing. * @param pThis The driver instance data. * @param pIoReq The request to remove. */ static void drvdiskintIoReqRemove(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq) { PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pIoReq->iSlot]; Assert(pReqActive->pIoReq == pIoReq); ASMAtomicWriteNullPtr(&pReqActive->pIoReq); }
static int pdmacFileAioMgrCloseEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint) { int rc = RTCritSectEnter(&pAioMgr->CritSectBlockingEvent); AssertRCReturn(rc, rc); ASMAtomicWritePtr(&pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint, pEndpoint); rc = pdmacFileAioMgrWaitForBlockingEvent(pAioMgr, PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT); ASMAtomicWriteNullPtr(&pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint); RTCritSectLeave(&pAioMgr->CritSectBlockingEvent); return rc; }
RTR3DECL(int) RTTlsFree(RTTLS iTls) { if (iTls == NIL_RTTLS) return VINF_SUCCESS; if ( iTls < 0 || iTls >= RTTHREAD_TLS_ENTRIES || !ASMBitTest(&g_au32AllocatedBitmap[0], iTls)) return VERR_INVALID_PARAMETER; ASMAtomicWriteNullPtr(&g_apfnDestructors[iTls]); rtThreadClearTlsEntry(iTls); ASMAtomicBitClear(&g_au32AllocatedBitmap[0], iTls); return VINF_SUCCESS; }
/** * 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; }
int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint) { LogFlowFunc(("pAioMgr=%#p pEndpoint=%#p{%s}\n", pAioMgr, pEndpoint, pEndpoint->Core.pszUri)); /* Update the assigned I/O manager. */ ASMAtomicWritePtr(&pEndpoint->pAioMgr, pAioMgr); int rc = RTCritSectEnter(&pAioMgr->CritSectBlockingEvent); AssertRCReturn(rc, rc); ASMAtomicWritePtr(&pAioMgr->BlockingEventData.AddEndpoint.pEndpoint, pEndpoint); rc = pdmacFileAioMgrWaitForBlockingEvent(pAioMgr, PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT); ASMAtomicWriteNullPtr(&pAioMgr->BlockingEventData.AddEndpoint.pEndpoint); RTCritSectLeave(&pAioMgr->CritSectBlockingEvent); return rc; }
RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq) { PRTFILEAIOREQINTERNAL pReqInt = hReq; RTFILEAIOREQ_VALID_RETURN(pReqInt); RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); ASMAtomicXchgBool(&pReqInt->fCanceled, true); int rcPosix = aio_cancel(pReqInt->AioCB.aio_fildes, &pReqInt->AioCB); if (rcPosix == AIO_CANCELED) { PRTFILEAIOCTXINTERNAL pCtxInt = pReqInt->pCtxInt; /* * Notify the waiting thread that the request was canceled. */ AssertMsg(VALID_PTR(pCtxInt), ("Invalid state. Request was canceled but wasn't submitted\n")); Assert(!pCtxInt->pReqToCancel); ASMAtomicWritePtr(&pCtxInt->pReqToCancel, pReqInt); rtFileAioCtxWakeup(pCtxInt); /* Wait for acknowledge. */ int rc = RTSemEventWait(pCtxInt->SemEventCancel, RT_INDEFINITE_WAIT); AssertRC(rc); ASMAtomicWriteNullPtr(&pCtxInt->pReqToCancel); pReqInt->Rc = VERR_FILE_AIO_CANCELED; RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); return VINF_SUCCESS; } else if (rcPosix == AIO_ALLDONE) return VERR_FILE_AIO_COMPLETED; else if (rcPosix == AIO_NOTCANCELED) return VERR_FILE_AIO_IN_PROGRESS; else return RTErrConvertFromErrno(errno); }