semeventmulti-r0drv-solaris.c revision 0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39c
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Solaris.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2006-2010 Oracle Corporation
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The contents of this file may alternatively be used under the terms
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * of the Common Development and Distribution License Version 1.0
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * CDDL are applicable instead of those of the GPL.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * You may elect to license modified versions of this file under the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * terms and conditions of either the GPL or the CDDL or both.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Header Files *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Defined Constants And Macros *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @name fStateAndGen values
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The state bit number. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The state mask. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define RTSEMEVENTMULTISOL_STATE_MASK RT_BIT_32(RTSEMEVENTMULTISOL_STATE_BIT)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The generation mask. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define RTSEMEVENTMULTISOL_GEN_MASK ~RTSEMEVENTMULTISOL_STATE_MASK
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The generation shift. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The initial variable value. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define RTSEMEVENTMULTISOL_STATE_GEN_INIT UINT32_C(0xfffffffc)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Structures and Typedefs *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Solaris multiple release event semaphore.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The number of references. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The object state bit and generation counter.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The generation counter is incremented every time the object is
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * signalled. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The Solaris mutex protecting this structure and pairing up the with the cv. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The Solaris condition variable. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync const char *pszNameFmt, ...)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(phEventMultiSem, VERR_INVALID_POINTER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertCompile(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->fStateAndGen = RTSEMEVENTMULTISOL_STATE_GEN_INIT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Retain a reference to the semaphore.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis The semaphore.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(void) rtR0SemEventMultiSolRetain(PRTSEMEVENTMULTIINTERNAL pThis)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Destructor that is called when cRefs == 0.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis The instance to destroy.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Release a reference, destroy the thing if necessary.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis The semaphore.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(void) rtR0SemEventMultiSolRelease(PRTSEMEVENTMULTIINTERNAL pThis)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn(pThis->cRefs > 0, ("pThis=%p cRefs=%d\n", pThis, pThis->cRefs), VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMAtomicWriteU32(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC_DEAD);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTISOL_GEN_MASK);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Drop the reference from RTSemEventMultiCreateEx. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * If we're in interrupt context we need to unpin the underlying current
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * thread as this could lead to a deadlock (see #4259 for the full explanation)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Note! See remarks about preemption in RTSemEventSignal.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Do the job.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t fNew = ASMAtomicUoReadU32(&pThis->fStateAndGen);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * If we're in interrupt context we need to unpin the underlying current
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * thread as this could lead to a deadlock (see #4259 for the full explanation)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Note! See remarks about preemption in RTSemEventSignal.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Do the job (could be done without the lock, but play safe).
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTISOL_STATE_MASK);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* -------- Move to header ---------- */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The absolute timeout given as nano seconds since the start of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * monotonic clock. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The timeout in nano seconds relative to the start of the wait. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The native timeout value. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The timeout (abs lbolt) when fHighRes is false. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Set if we use high resolution timeouts. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Set if it's an indefinite wait. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Set if we've already timed out.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Set by rtR0SemSolWaitDoIt or rtR0SemSolWaitHighResTimeout, read by
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * rtR0SemSolWaitHasTimedOut. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool volatile fTimedOut;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Whether the wait was interrupted. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Interruptible or uninterruptible wait. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The thread to wake up. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Cylic timer ID (used by the timeout callback). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a solaris semaphore wait structure. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Initializes a wait.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The caller MUST check the wait condition BEFORE calling this function or the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * timeout logic will be flawed.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VINF_SUCCESS or VERR_TIMEOUT.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pWait The wait structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param fFlags The wait flags.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param uTimeout The timeout.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pWaitQueue The wait queue head.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(int) rtR0SemSolWaitInit(PRTR0SEMSOLWAIT pWait, uint32_t fFlags, uint64_t uTimeout)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Process the flags and timeout.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || pWait->cNsRelTimeout < UINT32_C(1000000000) / 100 /*Hz*/ * 4)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint64_t cTicks = drv_usectohz((clock_t)(uTimeout / 1000));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pWait->fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Cyclic timeout callback that sets the timeout indicator and wakes up the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * waiting thread.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pvUser The wait structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void rtR0SemSolWaitHighResTimeout(void *pvUser)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Note: Trying to take the cpu_lock here doesn't work. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Do the actual wait.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pWait The wait structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pCnd The condition variable to wait on.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pMtx The mutex related to the condition variable.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The caller has entered this.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(void) rtR0SemSolWaitDoIt(PRTR0SEMSOLWAIT pWait, kcondvar_t *pCnd, kmutex_t *pMtx)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * No timeout - easy.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * High resolution timeout - arm a one-shot cyclic for waking up
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * the thread at the desired time.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Cyh.cyh_level = CY_LOW_LEVEL; /// @todo try CY_LOCK_LEVEL and CY_HIGH_LEVEL?
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Normal timeout.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = cv_timedwait_sig(pCnd, pMtx, pWait->u.lTimeout);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Above zero means normal wake-up. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Timeout is signalled by -1. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Interruption is signalled by 0. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Checks if a solaris wait was interrupted.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns true / false
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pWait The wait structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @remarks This shall be called before the first rtR0SemSolWaitDoIt().
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(bool) rtR0SemSolWaitWasInterrupted(PRTR0SEMSOLWAIT pWait)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Checks if a solaris wait has timed out.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns true / false
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pWait The wait structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(bool) rtR0SemSolWaitHasTimedOut(PRTR0SEMSOLWAIT pWait)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Deletes a solaris wait.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pWait The wait structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(void) rtR0SemSolWaitDelete(PRTR0SEMSOLWAIT pWait)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* -------- End ---------- */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis The event semaphore.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param fFlags See RTSemEventMultiWaitEx.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param uTimeout See RTSemEventMultiWaitEx.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pSrcPos The source code position of the wait.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int rtR0SemEventMultiSolWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Validate the input.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync mutex_enter(&pThis->Mtx); /* this could be moved down to the else, but play safe for now. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Is the event already signalled or do we have to wait?
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fOrgStateAndGen & RTSEMEVENTMULTISOL_STATE_MASK)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * We have to wait.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The destruction test. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Check the exit conditions. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Do the wait and then recheck the conditions. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, NULL);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();