daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * IPRT - Mutex Semaphores, Ring-0 Driver, Solaris.
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * available from http://www.virtualbox.org. This file is free software;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * you can redistribute it and/or modify it under the terms of the GNU
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * General Public License (GPL) as published by the Free Software
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * The contents of this file may alternatively be used under the terms
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * of the Common Development and Distribution License Version 1.0
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * VirtualBox OSE distribution, in which case the provisions of the
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * CDDL are applicable instead of those of the GPL.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * You may elect to license modified versions of this file under the
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * terms and conditions of either the GPL or the CDDL or both.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/*******************************************************************************
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync* Header Files *
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync*******************************************************************************/
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/*******************************************************************************
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync* Structures and Typedefs *
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync*******************************************************************************/
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Wrapper for the solaris semaphore structure.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** Magic value (RTSEMMUTEX_MAGIC). */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The number of recursions. */
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync /** The number of threads waiting for the mutex. */
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync /** The number of threads referencing us. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The owner thread, NIL_RTNATIVETHREAD if none. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The mutex object for synchronization. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The condition variable for synchronization. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Allocate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Initialize.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_init(&pThis->Mtx, "IPRT Mutex", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Invalidate the magic to indicate the mutex is being destroyed.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Wake up all waiters, last waiter thread cleans up.
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync * We're the last waiter, destroy.
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync * We're not the last waiting thread to be woken up. Just relinquish & bail.
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync * Worker for rtSemMutexSolRequest that handles the case where we go to sleep.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * @returns VINF_SUCCESS, VERR_INTERRUPTED, or VERR_SEM_DESTROYED.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Returns without owning the mutex.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * @param pThis The mutex instance.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * @param cMillies The timeout, must be > 0 or RT_INDEFINITE_WAIT.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * @param fInterruptible The wait type.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * @remarks This needs to be called with the mutex object held!
8750aef1556280f62aac28c3d97598db154b1ba6vboxsyncstatic int rtSemMutexSolRequestSleep(PRTSEMMUTEXINTERNAL pThis, RTMSINTERVAL cMillies,
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync * Now we wait (sleep; although might spin and then sleep) & reference the mutex.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Woken up by a release from another thread.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Interrupted by some signal.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Awakened due to the destruction-in-progress broadcast.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * We will cleanup if we're the last waiter.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Timed out.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Condition may not have been met, returned due to pending signal.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Internal worker.
8750aef1556280f62aac28c3d97598db154b1ba6vboxsyncDECLINLINE(int) rtSemMutexSolRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, bool fInterruptible)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Lock it and check if it's a recursion.
17b039ebafd914619c6be0465e1672d79ff72df7vboxsync * Not a recursion, claim the unowned mutex if we're there are no waiters.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else if ( pThis->hOwnerThread == NIL_RTNATIVETHREAD
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * A polling call?
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else if (cMillies == 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * No, we really need to get to sleep.
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync rc = rtSemMutexSolRequestSleep(pThis, cMillies, fInterruptible);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync return rtSemMutexSolRequest(hMutexSem, cMillies, false /*fInterruptible*/);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync return rtSemMutexSolRequest(hMutexSem, cMillies, true /*fInterruptible*/);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return RTSemMutexRequestNoResume(hMutexSem, cMillies);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Take the lock and release one recursion.
17b039ebafd914619c6be0465e1672d79ff72df7vboxsync * If there are any waiters, signal one of them.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), false);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Check if this is the owner.