semeventmulti-r0drv-solaris.c revision 1cf1be14d8a1ba2a1af75ba8d6b12078f1fb14d2
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Solaris.
1cb3b5cc4236e4c4c1d2fc0e35060181ffdc0669vboxsync * Copyright (C) 2006-2010 Oracle Corporation
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * available from http://www.virtualbox.org. This file is free software;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Header Files *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/*******************************************************************************
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync* Defined Constants And Macros *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync*******************************************************************************/
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** @name fStateAndGen values
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The state bit number. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The state mask. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_STATE_MASK RT_BIT_32(RTSEMEVENTMULTISOL_STATE_BIT)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The generation mask. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_GEN_MASK ~RTSEMEVENTMULTISOL_STATE_MASK
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The generation shift. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The initial variable value. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_STATE_GEN_INIT UINT32_C(0xfffffffc)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Structures and Typedefs *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync * Solaris multiple release event semaphore.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /** The number of references. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The object state bit and generation counter.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * The generation counter is incremented every time the object is
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * signalled. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The Solaris mutex protecting this structure and pairing up the with the cv. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The Solaris condition variable. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
ab93606043a9881487aa83be04191d2f4ea24071vboxsync const char *pszNameFmt, ...)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertPtrReturn(phEventMultiSem, VERR_INVALID_POINTER);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertCompile(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pThis->fStateAndGen = RTSEMEVENTMULTISOL_STATE_GEN_INIT;
249acff39649895e369c7d0c07d3d0adc4e10f38vboxsync mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Retain a reference to the semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(void) rtR0SemEventMultiSolRetain(PRTSEMEVENTMULTIINTERNAL pThis)
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync * Destructor that is called when cRefs == 0.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The instance to destroy.
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsyncstatic void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Release a reference, destroy the thing if necessary.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(void) rtR0SemEventMultiSolRelease(PRTSEMEVENTMULTIINTERNAL pThis)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync AssertMsgReturn(pThis->cRefs > 0, ("pThis=%p cRefs=%d\n", pThis, pThis->cRefs), VERR_INVALID_HANDLE);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicWriteU32(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC_DEAD);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTISOL_GEN_MASK);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Drop the reference from RTSemEventMultiCreateEx. */
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync * Do the job.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t fNew = ASMAtomicUoReadU32(&pThis->fStateAndGen);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Do the job (could be done without the lock, but play safe).
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTISOL_STATE_MASK);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @returns VBox status code.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The event semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param fFlags See RTSemEventMultiWaitEx.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param uTimeout See RTSemEventMultiWaitEx.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pSrcPos The source code position of the wait.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncstatic int rtR0SemEventMultiSolWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Validate the input.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_enter(&pThis->Mtx); /* this could be moved down to the else, but play safe for now. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Is the event already signalled or do we have to wait?
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (fOrgStateAndGen & RTSEMEVENTMULTISOL_STATE_MASK)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * We have to wait.
0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39cvboxsync /* The destruction test. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39cvboxsync /* Check the exit conditions. */
0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39cvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39cvboxsync else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39cvboxsync /* Do the wait and then recheck the conditions. */
0b7d24ee33cf513ef5a83fc9d6b9ba0a0427b39cvboxsync rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncRTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, NULL);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncRTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();