semeventmulti-r0drv-solaris.c revision ab93606043a9881487aa83be04191d2f4ea24071
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/* $Id$ */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Solaris.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync *
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 *
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 *
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 *
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
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Header Files *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include "the-solaris-kernel.h"
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include "internal/iprt.h"
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include <iprt/semaphore.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include <iprt/assert.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/asm.h>
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include <iprt/err.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/mem.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/mp.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/thread.h>
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include "internal/magics.h"
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Structures and Typedefs *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/**
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * FreeBSD multiple release event semaphore.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync */
089c21a647af46044cad04a78cfdcfae814d2105vboxsynctypedef struct RTSEMEVENTMULTIINTERNAL
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync uint32_t volatile u32Magic;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The number of waiting threads. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync uint32_t volatile cWaiters;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** Set if the event object is signaled. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync uint8_t volatile fSignaled;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The number of threads in the process of waking up. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync uint32_t volatile cWaking;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The Solaris mutex protecting this structure and pairing up the with the cv. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync kmutex_t Mtx;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** The Solaris condition variable. */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync kcondvar_t Cnd;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync}
ab93606043a9881487aa83be04191d2f4ea24071vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
ab93606043a9881487aa83be04191d2f4ea24071vboxsync const char *pszNameFmt, ...)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertPtrReturn(phEventMultiSem, VERR_INVALID_POINTER);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPTIBLE();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertCompile(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (pThis)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync pThis->cWaiters = 0;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync pThis->cWaking = 0;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync pThis->fSignaled = 0;
249acff39649895e369c7d0c07d3d0adc4e10f38vboxsync mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsync *phEventMultiSem = pThis;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VERR_NO_MEMORY;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
ab93606043a9881487aa83be04191d2f4ea24071vboxsync if (pThis == NIL_RTSEMEVENTMULTI)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return VINF_SUCCESS;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_INTS_ON();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_enter(&pThis->Mtx);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (pThis->cWaiters > 0)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* abort waiting thread, last man cleans up. */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync cv_broadcast(&pThis->Cnd);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync else if (pThis->cWaking)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* the last waking thread is gonna do the cleanup */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync else
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync cv_destroy(&pThis->Cnd);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_destroy(&pThis->Mtx);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync RTMemFree(pThis);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPT_CPUID_VAR();
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
089c21a647af46044cad04a78cfdcfae814d2105vboxsync VERR_INVALID_HANDLE);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_INTS_ON();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync /*
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 *
1564530634daa6810ea98bfc6dccb727728df853vboxsync * Note! See remarks about preemption in RTSemEventSignal.
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync */
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync int fAcquired = mutex_tryenter(&pThis->Mtx);
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync if (!fAcquired)
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync {
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync if (curthread->t_intr && getpil() < DISP_LEVEL)
542b82b1871753dc94a2a17b504094112f9df306vboxsync {
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTThreadPreemptDisable(&PreemptState);
542b82b1871753dc94a2a17b504094112f9df306vboxsync preempt();
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTThreadPreemptRestore(&PreemptState);
542b82b1871753dc94a2a17b504094112f9df306vboxsync }
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync mutex_enter(&pThis->Mtx);
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU8(&pThis->fSignaled, true);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (pThis->cWaiters > 0)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU32(&pThis->cWaiters, 0);
e53bd76507c13e8b4691d420a06c32c2f5e14b49vboxsync cv_broadcast(&pThis->Cnd);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPT_CPUID();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPT_CPUID_VAR();
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
089c21a647af46044cad04a78cfdcfae814d2105vboxsync VERR_INVALID_HANDLE);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_INTS_ON();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
1564530634daa6810ea98bfc6dccb727728df853vboxsync /*
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 *
1564530634daa6810ea98bfc6dccb727728df853vboxsync * Note! See remarks about preemption in RTSemEventSignal.
1564530634daa6810ea98bfc6dccb727728df853vboxsync */
1564530634daa6810ea98bfc6dccb727728df853vboxsync int fAcquired = mutex_tryenter(&pThis->Mtx);
1564530634daa6810ea98bfc6dccb727728df853vboxsync if (!fAcquired)
1564530634daa6810ea98bfc6dccb727728df853vboxsync {
1564530634daa6810ea98bfc6dccb727728df853vboxsync if (curthread->t_intr && getpil() < DISP_LEVEL)
542b82b1871753dc94a2a17b504094112f9df306vboxsync {
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTThreadPreemptDisable(&PreemptState);
542b82b1871753dc94a2a17b504094112f9df306vboxsync preempt();
542b82b1871753dc94a2a17b504094112f9df306vboxsync RTThreadPreemptRestore(&PreemptState);
542b82b1871753dc94a2a17b504094112f9df306vboxsync }
1564530634daa6810ea98bfc6dccb727728df853vboxsync mutex_enter(&pThis->Mtx);
1564530634daa6810ea98bfc6dccb727728df853vboxsync }
1564530634daa6810ea98bfc6dccb727728df853vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicXchgU8(&pThis->fSignaled, false);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPT_CPUID();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncstatic int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, unsigned cMillies, bool fInterruptible)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
089c21a647af46044cad04a78cfdcfae814d2105vboxsync int rc;
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
089c21a647af46044cad04a78cfdcfae814d2105vboxsync VERR_INVALID_HANDLE);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync if (cMillies)
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPTIBLE();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_enter(&pThis->Mtx);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (pThis->fSignaled)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync rc = VINF_SUCCESS;
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync else if (!cMillies)
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync rc = VERR_TIMEOUT;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync else
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
34f1d6d65a6bf02b2c3fdb7cf29f3c22fc749236vboxsync ASMAtomicIncU32(&pThis->cWaiters);
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /*
089c21a647af46044cad04a78cfdcfae814d2105vboxsync * Translate milliseconds into ticks and go to sleep.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync if (cMillies != RT_INDEFINITE_WAIT)
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync {
20444475973550995eb2369162a5a899fb6e3994vboxsync clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
38168c0b33d524f39a5d653675de79e1dbf5a558vboxsync clock_t cTimeout = ddi_get_lbolt();
38168c0b33d524f39a5d653675de79e1dbf5a558vboxsync cTimeout += cTicks;
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync if (fInterruptible)
38168c0b33d524f39a5d653675de79e1dbf5a558vboxsync rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync else
38168c0b33d524f39a5d653675de79e1dbf5a558vboxsync rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync }
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync else
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync {
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync if (fInterruptible)
34f1d6d65a6bf02b2c3fdb7cf29f3c22fc749236vboxsync rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync else
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync {
34f1d6d65a6bf02b2c3fdb7cf29f3c22fc749236vboxsync cv_wait(&pThis->Cnd, &pThis->Mtx);
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync rc = 1;
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync }
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync if (rc > 0)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* Retured due to call to cv_signal() or cv_broadcast() */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync rc = VINF_SUCCESS;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync else
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
089c21a647af46044cad04a78cfdcfae814d2105vboxsync rc = VERR_SEM_DESTROYED;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (!ASMAtomicDecU32(&pThis->cWaking))
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync cv_destroy(&pThis->Cnd);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_destroy(&pThis->Mtx);
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync RTMemFree(pThis);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return rc;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicDecU32(&pThis->cWaking);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync else if (rc == -1)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* Returned due to timeout being reached */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (pThis->cWaiters > 0)
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicDecU32(&pThis->cWaiters);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync rc = VERR_TIMEOUT;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync else
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /* Returned due to pending signal */
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync if (pThis->cWaiters > 0)
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync ASMAtomicDecU32(&pThis->cWaiters);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync rc = VERR_INTERRUPTED;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return rc;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, unsigned cMillies)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, false /* not interruptible */);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, unsigned cMillies)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, true /* interruptible */);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync