semevent-r0drv-solaris.c revision e0e7da0420be1398d23ffa9953686d3a43619abd
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * IPRT - Single Release Event Semaphores, Ring-0 Driver, Solaris.
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * Copyright (C) 2006-2010 Oracle Corporation
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * available from http://www.virtualbox.org. This file is free software;
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * General Public License (GPL) as published by the Free Software
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * CDDL are applicable instead of those of the GPL.
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync * You may elect to license modified versions of this file under the
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync * terms and conditions of either the GPL or the CDDL or both.
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync/*******************************************************************************
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync* Header Files *
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync*******************************************************************************/
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync/*******************************************************************************
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync* Structures and Typedefs *
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync*******************************************************************************/
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * Waiter entry. Lives on the stack.
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * @remarks Unfortunately, we cannot easily use cv_signal because we cannot
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * distinguish between it and the spurious wakeups we get after fork.
9a08dd6ed47cffa9cacbb9d53db1ce71d04db61fvboxsync * So, we keep an unprioritized FIFO with the sleeping threads.
9a08dd6ed47cffa9cacbb9d53db1ce71d04db61fvboxsync /** The list node. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** The thread. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** Flag set when waking up the thread by signal or destroy. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync bool volatile fWokenUp;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync/** Pointer to waiter entry. */
b459362b1c9b5ce5e6bf4ceb32ffe1294c08be07vboxsync * Solaris event semaphore.
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync /** Magic value (RTSEMEVENT_MAGIC). */
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync /** The number of threads referencing this object. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** Set if the object is signalled when there are no waiters. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** List of waiting and woken up threads. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** The Solaris mutex protecting this structure and pairing up the with the cv. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** The Solaris condition variable. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsyncRTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
cfd41a3683178a30bac4417128b4673806653797vboxsyncRTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
cfd41a3683178a30bac4417128b4673806653797vboxsync AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
cfd41a3683178a30bac4417128b4673806653797vboxsync AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
613c0d015cbaef93be47fc03f0708744c5c24f79vboxsync mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * Retain a reference to the semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pThis The semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncDECLINLINE(void) rtR0SemEventSolRetain(PRTSEMEVENTINTERNAL pThis)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * The destruct.
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync * @param pThis The semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncstatic void rtR0SemEventSolDtor(PRTSEMEVENTINTERNAL pThis)
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync * Release a reference, destroy the thing if necessary.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pThis The semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncDECLINLINE(void) rtR0SemEventSolRelease(PRTSEMEVENTINTERNAL pThis)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Validate input.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Invalidate the semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Abort and wake up all threads.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Release the reference from RTSemEventCreateEx.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Wake up one thread.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @returns VBox status code.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pThis The event semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param fFlags See RTSemEventWaitEx.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param uTimeout See RTSemEventWaitEx.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pSrcPos The source code position of the wait.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncstatic int rtR0SemEventSolWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Validate the input.
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync * In the signaled state?
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync if (ASMAtomicCmpXchgBool(&pThis->fSignaled, false, true))
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync * We have to wait.
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync RTSEMEVENTSOLENTRY Waiter; /* ASSUMES we won't get swapped out while waiting (TS_DONT_SWAP). */
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync /* The destruction test. */
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /* Check the exit conditions. */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /* Do the wait and then recheck the conditions. */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncRTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
97674677e4f2aeae576c39f966568dd664ba7979vboxsync return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, NULL);
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
return rtR0SemSolWaitGetResolution();