semeventmulti-r0drv-solaris.c revision da268f8e500646ade99e808a0d8ec0036ac703b0
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Solaris.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Header Files *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Structures and Typedefs *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * FreeBSD multiple release event semaphore.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The number of waiting threads. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** Set if the event object is signaled. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The number of threads in the process of waking up. */
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));
249acff39649895e369c7d0c07d3d0adc4e10f38vboxsync mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
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);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* abort waiting thread, last man cleans up. */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* the last waking thread is gonna do the cleanup */
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync * If we're in interrupt context we need to unpin the underlying current
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync * thread as this could lead to a deadlock (see #4259 for the full explanation)
1564530634daa6810ea98bfc6dccb727728df853vboxsync * Note! See remarks about preemption in RTSemEventSignal.
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1564530634daa6810ea98bfc6dccb727728df853vboxsync * If we're in interrupt context we need to unpin the underlying current
1564530634daa6810ea98bfc6dccb727728df853vboxsync * thread as this could lead to a deadlock (see #4259 for the full explanation)
1564530634daa6810ea98bfc6dccb727728df853vboxsync * Note! See remarks about preemption in RTSemEventSignal.
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncstatic int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, bool fInterruptible)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * Translate milliseconds into ticks and go to sleep.
20444475973550995eb2369162a5a899fb6e3994vboxsync clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
38168c0b33d524f39a5d653675de79e1dbf5a558vboxsync rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
38168c0b33d524f39a5d653675de79e1dbf5a558vboxsync rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* Retured due to call to cv_signal() or cv_broadcast() */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* Returned due to timeout being reached */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* Returned due to pending signal */
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncRTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, false /* not interruptible */);
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncRTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, true /* interruptible */);