/** * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug. * * @returns VBox status code. * @param pThis The event semaphore. * @param fFlags See RTSemEventWaitEx. * @param uTimeout See RTSemEventWaitEx. * @param pSrcPos The source code position of the wait. */ static int rtR0SemEventWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) { int rc; /* * Validate the input. */ AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); rtR0SemEventBsdRetain(pThis); /* * Try grab the event without setting up the wait. */ if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) rc = VINF_SUCCESS; else { /* * We have to wait. */ RTR0SEMBSDSLEEP Wait; rc = rtR0SemBsdWaitInit(&Wait, fFlags, uTimeout, pThis); if (RT_SUCCESS(rc)) { for (;;) { /* The destruction test. */ if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) rc = VERR_SEM_DESTROYED; else { rtR0SemBsdWaitPrepare(&Wait); /* Check the exit conditions. */ if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) rc = VERR_SEM_DESTROYED; else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) rc = VINF_SUCCESS; else if (rtR0SemBsdWaitHasTimedOut(&Wait)) rc = VERR_TIMEOUT; else if (rtR0SemBsdWaitWasInterrupted(&Wait)) rc = VERR_INTERRUPTED; else { /* Do the wait and then recheck the conditions. */ rtR0SemBsdWaitDoIt(&Wait); continue; } } break; } rtR0SemBsdWaitDelete(&Wait); } } rtR0SemEventBsdRelease(pThis); return rc; }
/** * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug. * * @returns VBox status code. * @param pThis The event semaphore. * @param fFlags See RTSemEventMultiWaitEx. * @param uTimeout See RTSemEventMultiWaitEx. * @param pSrcPos The source code position of the wait. */ static int rtR0SemEventMultiBsdWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) { uint32_t fOrgStateAndGen; int rc; /* * Validate the input. */ AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); rtR0SemEventMultiBsdRetain(pThis); /* * Is the event already signalled or do we have to wait? */ fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen); if (fOrgStateAndGen & RTSEMEVENTMULTIBSD_STATE_MASK) rc = VINF_SUCCESS; else { /* * We have to wait. */ RTR0SEMBSDSLEEP Wait; rc = rtR0SemBsdWaitInit(&Wait, fFlags, uTimeout, pThis); if (RT_SUCCESS(rc)) { for (;;) { /* The destruction test. */ if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) rc = VERR_SEM_DESTROYED; else { rtR0SemBsdWaitPrepare(&Wait); /* Check the exit conditions. */ if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) rc = VERR_SEM_DESTROYED; else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen) rc = VINF_SUCCESS; else if (rtR0SemBsdWaitHasTimedOut(&Wait)) rc = VERR_TIMEOUT; else if (rtR0SemBsdWaitWasInterrupted(&Wait)) rc = VERR_INTERRUPTED; else { /* Do the wait and then recheck the conditions. */ rtR0SemBsdWaitDoIt(&Wait); continue; } } break; } rtR0SemBsdWaitDelete(&Wait); } } rtR0SemEventMultiBsdRelease(pThis); return rc; }