static int rtR0ThreadOs2SleepCommon(RTMSINTERVAL cMillies) { int rc = KernBlock((ULONG)RTThreadSleep, cMillies == RT_INDEFINITE_WAIT ? SEM_INDEFINITE_WAIT : cMillies, 0, NULL, NULL); switch (rc) { case NO_ERROR: return VINF_SUCCESS; case ERROR_TIMEOUT: return VERR_TIMEOUT; case ERROR_INTERRUPT: return VERR_INTERRUPTED; default: AssertMsgFailed(("%d\n", rc)); return VERR_NO_TRANSLATION; } }
/** * 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 rtR0SemEventMultiOs2Wait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) { /* * Validate and convert the input. */ if (!pThis) return VERR_INVALID_HANDLE; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); ULONG cMsTimeout = rtR0SemWaitOs2ConvertTimeout(fFlags, uTimeout); ULONG fBlock = BLOCK_SPINLOCK; if (!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE)) fBlock |= BLOCK_UNINTERRUPTABLE; /* * Do the job. */ KernAcquireSpinLock(&pThis->Spinlock); int rc; if (pThis->fSignaled) rc = VINF_SUCCESS; else { ASMAtomicIncU32(&pThis->cWaiters); ULONG ulData = (ULONG)VERR_INTERNAL_ERROR; rc = KernBlock((ULONG)pThis, cMsTimeout, fBlock, &pThis->Spinlock, &ulData); switch (rc) { case NO_ERROR: rc = (int)ulData; Assert(rc == VINF_SUCCESS || rc == VERR_SEM_DESTROYED); Assert(pThis->cWaking > 0); if ( !ASMAtomicDecU32(&pThis->cWaking) && pThis->u32Magic != RTSEMEVENTMULTI_MAGIC) { /* The event was destroyed (ulData == VINF_SUCCESS if it was after we awoke), as the last thread do the cleanup. */ KernReleaseSpinLock(&pThis->Spinlock); KernFreeSpinLock(&pThis->Spinlock); RTMemFree(pThis); return VINF_SUCCESS; } rc = VINF_SUCCESS; break; case ERROR_TIMEOUT: Assert(cMsTimeout != SEM_INDEFINITE_WAIT); ASMAtomicDecU32(&pThis->cWaiters); rc = VERR_TIMEOUT; break; case ERROR_INTERRUPT: Assert(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE); ASMAtomicDecU32(&pThis->cWaiters); rc = VERR_INTERRUPTED; break; default: AssertMsgFailed(("rc=%d\n", rc)); rc = VERR_GENERAL_FAILURE; break; } } KernReleaseSpinLock(&pThis->Spinlock); return rc; }