daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/* $Id$ */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/** @file
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * IPRT - Mutex Semaphores, Ring-0 Driver, Solaris.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync *
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 *
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 *
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
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/*******************************************************************************
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync* Header Files *
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync*******************************************************************************/
715e49c31b15c23c17a9ce3be42a75e7c48d4b78vboxsync#define RTSEMMUTEX_WITHOUT_REMAPPING
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include "the-solaris-kernel.h"
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include "internal/iprt.h"
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/semaphore.h>
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/assert.h>
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/asm.h>
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync# include <iprt/asm-amd64-x86.h>
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync#endif
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/mem.h>
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/err.h>
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/list.h>
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include <iprt/thread.h>
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync#include "internal/magics.h"
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/*******************************************************************************
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync* Structures and Typedefs *
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync*******************************************************************************/
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/**
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Wrapper for the solaris semaphore structure.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsynctypedef struct RTSEMMUTEXINTERNAL
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** Magic value (RTSEMMUTEX_MAGIC). */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync uint32_t u32Magic;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The number of recursions. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync uint32_t cRecursions;
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync /** The number of threads waiting for the mutex. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync uint32_t volatile cWaiters;
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync /** The number of threads referencing us. */
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync uint32_t volatile cRefs;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The owner thread, NIL_RTNATIVETHREAD if none. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync RTNATIVETHREAD hOwnerThread;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The mutex object for synchronization. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync kmutex_t Mtx;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /** The condition variable for synchronization. */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync kcondvar_t Cnd;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMtx)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Allocate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (RT_UNLIKELY(!pThis))
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return VERR_NO_MEMORY;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Initialize.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->u32Magic = RTSEMMUTEX_MAGIC;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->cRecursions = 0;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->cWaiters = 0;
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync pThis->cRefs = 1;
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync pThis->hOwnerThread = NIL_RTNATIVETHREAD;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_init(&pThis->Mtx, "IPRT Mutex", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync cv_init(&pThis->Cnd, "IPRT CVM", CV_DRIVER, NULL);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync *phMtx = pThis;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMtx)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync PRTSEMMUTEXINTERNAL pThis = hMtx;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (pThis == NIL_RTSEMMUTEX)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_enter(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync ASMAtomicDecU32(&pThis->cRefs);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Invalidate the magic to indicate the mutex is being destroyed.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync ASMAtomicIncU32(&pThis->u32Magic);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (pThis->cWaiters > 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Wake up all waiters, last waiter thread cleans up.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync cv_broadcast(&pThis->Cnd);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_exit(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync else if (pThis->cRefs == 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync * We're the last waiter, destroy.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_exit(&pThis->Mtx);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync cv_destroy(&pThis->Cnd);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync mutex_destroy(&pThis->Mtx);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync RTMemFree(pThis);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync * We're not the last waiting thread to be woken up. Just relinquish & bail.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_exit(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/**
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync * Worker for rtSemMutexSolRequest that handles the case where we go to sleep.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync *
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 *
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * @remarks This needs to be called with the mutex object held!
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
8750aef1556280f62aac28c3d97598db154b1ba6vboxsyncstatic int rtSemMutexSolRequestSleep(PRTSEMMUTEXINTERNAL pThis, RTMSINTERVAL cMillies,
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync bool fInterruptible)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync int rc = VERR_GENERAL_FAILURE;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync Assert(cMillies > 0);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync * Now we wait (sleep; although might spin and then sleep) & reference the mutex.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync ASMAtomicIncU32(&pThis->cWaiters);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync ASMAtomicIncU32(&pThis->cRefs);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (cMillies != RT_INDEFINITE_WAIT)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync clock_t cTimeout = ddi_get_lbolt();
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync cTimeout += cTicks;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (fInterruptible)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (fInterruptible)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync cv_wait(&pThis->Cnd, &pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = 1;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync ASMAtomicDecU32(&pThis->cWaiters);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (rc > 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (pThis->u32Magic == RTSEMMUTEX_MAGIC)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync if (pThis->hOwnerThread == NIL_RTNATIVETHREAD)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Woken up by a release from another thread.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync Assert(pThis->cRecursions == 0);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync pThis->cRecursions = 1;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->hOwnerThread = RTThreadNativeSelf();
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Interrupted by some signal.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
17b039ebafd914619c6be0465e1672d79ff72df7vboxsync rc = VERR_INTERRUPTED;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Awakened due to the destruction-in-progress broadcast.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * We will cleanup if we're the last waiter.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VERR_SEM_DESTROYED;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else if (rc == -1)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Timed out.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VERR_TIMEOUT;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Condition may not have been met, returned due to pending signal.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VERR_INTERRUPTED;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync if (!ASMAtomicDecU32(&pThis->cRefs))
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync {
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync Assert(RT_FAILURE_NP(rc));
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync mutex_exit(&pThis->Mtx);
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync cv_destroy(&pThis->Cnd);
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync mutex_destroy(&pThis->Mtx);
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync RTMemFree(pThis);
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync return rc;
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync }
6f5f5d91362551197191292190ddfa2d7457a63bvboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return rc;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync/**
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Internal worker.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
8750aef1556280f62aac28c3d97598db154b1ba6vboxsyncDECLINLINE(int) rtSemMutexSolRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, bool fInterruptible)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync PRTSEMMUTEXINTERNAL pThis = hMutexSem;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync int rc = VERR_GENERAL_FAILURE;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync Assert(pThis->cRefs >= 1);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Lock it and check if it's a recursion.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_enter(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (pThis->hOwnerThread == RTThreadNativeSelf())
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->cRecursions++;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync Assert(pThis->cRecursions > 1);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync Assert(pThis->cRecursions < 256);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
17b039ebafd914619c6be0465e1672d79ff72df7vboxsync * Not a recursion, claim the unowned mutex if we're there are no waiters.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else if ( pThis->hOwnerThread == NIL_RTNATIVETHREAD
c78f8922c7119f57444bc328c4f07ec692a90e0evboxsync && pThis->cWaiters == 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->cRecursions = 1;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->hOwnerThread = RTThreadNativeSelf();
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * A polling call?
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else if (cMillies == 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VERR_TIMEOUT;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * No, we really need to get to sleep.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync rc = rtSemMutexSolRequestSleep(pThis, cMillies, fInterruptible);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_exit(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return rc;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync return rtSemMutexSolRequest(hMutexSem, cMillies, false /*fInterruptible*/);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return RTSemMutexRequest(hMutexSem, cMillies);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync return rtSemMutexSolRequest(hMutexSem, cMillies, true /*fInterruptible*/);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return RTSemMutexRequestNoResume(hMutexSem, cMillies);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMtx)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync PRTSEMMUTEXINTERNAL pThis = hMtx;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync int rc;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Take the lock and release one recursion.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_enter(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (pThis->hOwnerThread == RTThreadNativeSelf())
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync Assert(pThis->cRecursions > 0);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (--pThis->cRecursions == 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync {
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync pThis->hOwnerThread = NIL_RTNATIVETHREAD;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
17b039ebafd914619c6be0465e1672d79ff72df7vboxsync * If there are any waiters, signal one of them.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync if (pThis->cWaiters > 0)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync cv_signal(&pThis->Cnd);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VINF_SUCCESS;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync }
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync else
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync rc = VERR_NOT_OWNER;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_exit(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return rc;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsyncRTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync{
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync PRTSEMMUTEXINTERNAL pThis = hMutexSem;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync bool fOwned = false;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Validate.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertPtrReturn(pThis, false);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), false);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync /*
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync * Check if this is the owner.
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync */
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_enter(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync fOwned = pThis->hOwnerThread != NIL_RTNATIVETHREAD;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync mutex_exit(&pThis->Mtx);
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync return fOwned;
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync}
daa0693c677c252de7722cca34391b39e8fcf1a3vboxsync