semeventmulti-r0drv-solaris.c revision b9c00cd9c9b5f409e64bd7782815faa2c5ecd85f
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/* $Id$ */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Solaris.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*
1cb3b5cc4236e4c4c1d2fc0e35060181ffdc0669vboxsync * Copyright (C) 2006-2010 Oracle Corporation
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.
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>
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync# include <iprt/asm-amd64-x86.h>
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync#endif
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include <iprt/err.h>
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#include <iprt/lockvalidator.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/mem.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/mp.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/thread.h>
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#include <iprt/time.h>
089c21a647af46044cad04a78cfdcfae814d2105vboxsync#include "internal/magics.h"
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/*******************************************************************************
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync* Defined Constants And Macros *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync*******************************************************************************/
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** @name fStateAndGen values
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @{ */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The state bit number. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_STATE_BIT 0
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The state mask. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_STATE_MASK RT_BIT_32(RTSEMEVENTMULTISOL_STATE_BIT)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The generation mask. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_GEN_MASK ~RTSEMEVENTMULTISOL_STATE_MASK
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The generation shift. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_GEN_SHIFT 1
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** The initial variable value. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#define RTSEMEVENTMULTISOL_STATE_GEN_INIT UINT32_C(0xfffffffc)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/** @} */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/*******************************************************************************
089c21a647af46044cad04a78cfdcfae814d2105vboxsync* Structures and Typedefs *
089c21a647af46044cad04a78cfdcfae814d2105vboxsync*******************************************************************************/
089c21a647af46044cad04a78cfdcfae814d2105vboxsync/**
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync * Solaris multiple release event semaphore.
089c21a647af46044cad04a78cfdcfae814d2105vboxsync */
089c21a647af46044cad04a78cfdcfae814d2105vboxsynctypedef struct RTSEMEVENTMULTIINTERNAL
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
089c21a647af46044cad04a78cfdcfae814d2105vboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync uint32_t volatile u32Magic;
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /** The number of references. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t volatile cRefs;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The object state bit and generation counter.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * The generation counter is incremented every time the object is
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * signalled. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t volatile fStateAndGen;
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 {
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync pThis->cRefs = 1;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pThis->fStateAndGen = RTSEMEVENTMULTISOL_STATE_GEN_INIT;
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
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Retain a reference to the semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(void) rtR0SemEventMultiSolRetain(PRTSEMEVENTMULTIINTERNAL pThis)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Assert(cRefs && cRefs < 100000);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync/**
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync * Destructor that is called when cRefs == 0.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The instance to destroy.
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync */
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsyncstatic void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis)
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync cv_destroy(&pThis->Cnd);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync mutex_destroy(&pThis->Mtx);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync RTMemFree(pThis);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync}
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Release a reference, destroy the thing if necessary.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(void) rtR0SemEventMultiSolRelease(PRTSEMEVENTMULTIINTERNAL pThis)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtSemEventMultiDtor(pThis);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
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);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync AssertMsgReturn(pThis->cRefs > 0, ("pThis=%p cRefs=%d\n", pThis, pThis->cRefs), VERR_INVALID_HANDLE);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_INTS_ON();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_enter(&pThis->Mtx);
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicWriteU32(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC_DEAD);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTISOL_GEN_MASK);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync cv_broadcast(&pThis->Cnd);
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Drop the reference from RTSemEventMultiCreateEx. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_exit(&pThis->Mtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRelease(pThis);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsyncRTDECL(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();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRetain(pThis);
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 }
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /*
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync * Do the job.
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t fNew = ASMAtomicUoReadU32(&pThis->fStateAndGen);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fNew += 1 << RTSEMEVENTMULTISOL_GEN_SHIFT;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fNew |= RTSEMEVENTMULTISOL_STATE_MASK;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicWriteU32(&pThis->fStateAndGen, fNew);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync cv_broadcast(&pThis->Cnd);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRelease(pThis);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPT_CPUID();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsyncRTDECL(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();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRetain(pThis);
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 }
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
1564530634daa6810ea98bfc6dccb727728df853vboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Do the job (could be done without the lock, but play safe).
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTISOL_STATE_MASK);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_exit(&pThis->Mtx);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRelease(pThis);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPT_CPUID();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return VINF_SUCCESS;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#if 0 /* NEW_STUFF - not working yet :-) */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsynctypedef struct RTR0SEMSOLWAIT
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The absolute timeout given as nano seconds since the start of the
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * monotonic clock. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint64_t uNsAbsTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The timeout in nano seconds relative to the start of the wait. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint64_t cNsRelTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The native timeout value. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync union
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The timeout (abs lbolt) when fHighRes is false. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync clock_t lTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync } u;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** Set if we use high resolution timeouts. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync bool fHighRes;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** Set if it's an indefinite wait. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync bool fIndefinite;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** Set if we've already timed out.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Set by rtR0SemSolWaitDoIt or rtR0SemSolWaitHighResTimeout, read by
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * rtR0SemSolWaitHasTimedOut. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync bool volatile fTimedOut;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** Whether the wait was interrupted. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync bool fInterrupted;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** Interruptible or uninterruptible wait. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync bool fInterruptible;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /** The thread to wake up. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync kthread_t *pThread;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync} RTR0SEMSOLWAIT;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsynctypedef RTR0SEMSOLWAIT *PRTR0SEMSOLWAIT;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Initializes a wait.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * The caller MUST check the wait condition BEFORE calling this function or the
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * timeout logic will be flawed.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @returns VINF_SUCCESS or VERR_TIMEOUT.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pWait The wait structure.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param fFlags The wait flags.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param uTimeout The timeout.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pWaitQueue The wait queue head.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(int) rtR0SemSolWaitInit(PRTR0SEMSOLWAIT pWait, uint32_t fFlags, uint64_t uTimeout)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Process the flags and timeout.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ? uTimeout * UINT32_C(1000000)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync : UINT64_MAX;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (uTimeout == UINT64_MAX)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint64_t u64Now;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (uTimeout == 0)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return VERR_TIMEOUT;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync u64Now = RTTimeSystemNanoTS();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->cNsRelTimeout = uTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->uNsAbsTimeout = u64Now + uTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pWait->uNsAbsTimeout < u64Now) /* overflow */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync u64Now = RTTimeSystemNanoTS();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (u64Now >= uTimeout)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return VERR_TIMEOUT;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->cNsRelTimeout = uTimeout - u64Now;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->uNsAbsTimeout = uTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fIndefinite = false;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if ( (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync || pWait->cNsRelTimeout < UINT32_C(1000000000) / 100 /*Hz*/ * 4)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fHighRes = true;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#if 1
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint64_t cTicks = NSEC_TO_TICK_ROUNDUP(uTimeout);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint64_t cTicks = drv_usectohz((clock_t)(uTimeout / 1000));
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#endif
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (cTicks >= LONG_MAX)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->u.lTimeout = ddi_get_lbolt() + cTicks;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fHighRes = false;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fIndefinite = true;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fHighRes = false;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->uNsAbsTimeout = UINT64_MAX;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->cNsRelTimeout = UINT64_MAX;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->u.lTimeout = LONG_MAX;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fTimedOut = false;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fInterrupted = false;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->pThread = curthread;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return VINF_SUCCESS;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Cyclic timeout callback that sets the timeout indicator and wakes up the
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * waiting thread.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pvUser The wait structure.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncstatic void rtR0SemSolWaitHighResTimeout(void *pvUser)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync PRTR0SEMSOLWAIT pWait = (PRTR0SEMSOLWAIT)pvUser;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync kthread_t *pThread = pWait->pThread;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (VALID_PTR(pThread)) /* paranoia */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync ASMAtomicWriteBool(&pWait->fTimedOut, true);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync setrun(pThread);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Do the actual wait.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pWait The wait structure.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pCnd The condition variable to wait on.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pMtx The mutex related to the condition variable.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * The caller has entered this.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(void) rtR0SemSolWaitDoIt(PRTR0SEMSOLWAIT pWait, kcondvar_t *pCnd, kmutex_t *pMtx)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync int rc = 1;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pWait->fIndefinite)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * No timeout - easy.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pWait->fInterruptible)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = cv_wait_sig(pCnd, pMtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync cv_wait(pCnd, pMtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else if (pWait->fHighRes)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * High resolution timeout - arm a one-shot cyclic for waking up
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * the thread at the desired time.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync cyc_handler_t Cyh;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Cyh.cyh_arg = pWait;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Cyh.cyh_func = rtR0SemSolWaitHighResTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Cyh.cyh_level = CY_LOW_LEVEL; /// @todo try CY_LOCK_LEVEL and CY_HIGH_LEVEL?
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync cyc_time_t Cyt;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Cyt.cyt_when = pWait->uNsAbsTimeout;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync Cyt.cyt_interval = 0;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_enter(&cpu_lock);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync cyclic_id_t idCy = cyclic_add(&Cyh, &Cyt);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_exit(&cpu_lock);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pWait->fInterruptible)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = cv_wait_sig(pCnd, pMtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync cv_wait(pCnd, pMtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_enter(&cpu_lock);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync cyclic_remove(idCy);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_exit(&cpu_lock);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Normal timeout.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pWait->fInterruptible)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = cv_timedwait_sig(pCnd, pMtx, pWait->u.lTimeout);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = cv_timedwait(pCnd, pMtx, pWait->u.lTimeout);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /* Above zero means normal wake-up. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (rc > 0)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /* Timeout is signalled by -1. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (rc == -1)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fTimedOut = true;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /* Interruption is signalled by 0. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync AssertMsg(rc == 0, ("rc=%d\n", rc));
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->fInterrupted = true;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Checks if a solaris wait was interrupted.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @returns true / false
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pWait The wait structure.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @remarks This shall be called before the first rtR0SemSolWaitDoIt().
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(bool) rtR0SemSolWaitWasInterrupted(PRTR0SEMSOLWAIT pWait)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return pWait->fInterrupted;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Checks if a solaris wait has timed out.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @returns true / false
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pWait The wait structure.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(bool) rtR0SemSolWaitHasTimedOut(PRTR0SEMSOLWAIT pWait)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return pWait->fTimedOut;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Deletes a solaris wait.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pWait The wait structure.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncDECLINLINE(void) rtR0SemSolWaitDelete(PRTR0SEMSOLWAIT pWait)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync pWait->pThread = NULL;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync/**
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync *
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @returns VBox status code.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pThis The event semaphore.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param fFlags See RTSemEventMultiWaitEx.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param uTimeout See RTSemEventMultiWaitEx.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * @param pSrcPos The source code position of the wait.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncstatic int rtR0SemEventMultiSolWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync PCRTLOCKVALSRCPOS pSrcPos)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t fOrgStateAndGen;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync int rc;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Validate the input.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRetain(pThis);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_enter(&pThis->Mtx); /* this could be moved down to the else, but play safe for now. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * Is the event already signalled or do we have to wait?
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (fOrgStateAndGen & RTSEMEVENTMULTISOL_STATE_MASK)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = VINF_SUCCESS;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /*
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync * We have to wait.
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync RTR0SEMSOLWAIT Wait;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemSolWaitInit(&Wait, fFlags, uTimeout);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync for (;;)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /* The destruction test. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = VERR_SEM_DESTROYED;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /* Check the exit conditions. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = VERR_SEM_DESTROYED;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = VINF_SUCCESS;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else if (rtR0SemSolWaitHasTimedOut(&Wait))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = VERR_TIMEOUT;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else if (rtR0SemSolWaitWasInterrupted(&Wait))
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rc = VERR_INTERRUPTED;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync /* Do the wait and then recheck the conditions. */
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync continue;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync break;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemSolWaitDelete(&Wait);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync }
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_exit(&pThis->Mtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRelease(pThis);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return rc;
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#undef RTSemEventMultiWaitEx
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncRTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#ifndef RTSEMEVENT_STRICT
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, NULL);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#else
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#endif
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsyncRTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync RTHCUINTPTR uId, RT_SRC_POS_DECL)
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync{
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync}
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#include "../../generic/RTSemEventMultiWait-2-ex-generic.cpp"
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#include "../../generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp"
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#else /* OLD_STUFF */
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync/**
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync * Translate milliseconds into ticks and go to sleep using the right method.
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync *
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync * @retval >0 on normal or spurious wake-up.
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync * @retval -1 on timeout.
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync * @retval 0 on signal.
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync */
4add215f9918fd37934b252922caab7803aaac19vboxsyncstatic int rtSemEventMultiWaitWorker(PRTSEMEVENTMULTIINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
4add215f9918fd37934b252922caab7803aaac19vboxsync{
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync int rc;
4add215f9918fd37934b252922caab7803aaac19vboxsync if (cMillies != RT_INDEFINITE_WAIT)
4add215f9918fd37934b252922caab7803aaac19vboxsync {
4add215f9918fd37934b252922caab7803aaac19vboxsync clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
4add215f9918fd37934b252922caab7803aaac19vboxsync clock_t cTimeout = ddi_get_lbolt();
4add215f9918fd37934b252922caab7803aaac19vboxsync cTimeout += cTicks;
4add215f9918fd37934b252922caab7803aaac19vboxsync if (fInterruptible)
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
4add215f9918fd37934b252922caab7803aaac19vboxsync else
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
4add215f9918fd37934b252922caab7803aaac19vboxsync }
4add215f9918fd37934b252922caab7803aaac19vboxsync else
4add215f9918fd37934b252922caab7803aaac19vboxsync {
4add215f9918fd37934b252922caab7803aaac19vboxsync if (fInterruptible)
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
4add215f9918fd37934b252922caab7803aaac19vboxsync else
4add215f9918fd37934b252922caab7803aaac19vboxsync {
4add215f9918fd37934b252922caab7803aaac19vboxsync cv_wait(&pThis->Cnd, &pThis->Mtx);
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = 1;
4add215f9918fd37934b252922caab7803aaac19vboxsync }
4add215f9918fd37934b252922caab7803aaac19vboxsync }
4add215f9918fd37934b252922caab7803aaac19vboxsync return rc;
4add215f9918fd37934b252922caab7803aaac19vboxsync}
4add215f9918fd37934b252922caab7803aaac19vboxsync
4add215f9918fd37934b252922caab7803aaac19vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncstatic int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL 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);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRetain(pThis);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync if (cMillies)
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPTIBLE();
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync mutex_enter(&pThis->Mtx);
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pThis->fStateAndGen & RTSEMEVENTMULTISOL_STATE_MASK)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync rc = VINF_SUCCESS;
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync else if (!cMillies)
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync rc = VERR_TIMEOUT;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync else
089c21a647af46044cad04a78cfdcfae814d2105vboxsync {
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync /* This loop is only for continuing after a spurious wake-up. */
4add215f9918fd37934b252922caab7803aaac19vboxsync for (;;)
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync uint32_t const uSignalGenBeforeWait = pThis->fStateAndGen;
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = rtSemEventMultiWaitWorker(pThis, cMillies, fInterruptible);
4add215f9918fd37934b252922caab7803aaac19vboxsync if (rc > 0)
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync {
4add215f9918fd37934b252922caab7803aaac19vboxsync if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
4add215f9918fd37934b252922caab7803aaac19vboxsync {
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync if (pThis->fStateAndGen == uSignalGenBeforeWait)
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync continue; /* Spurious wake-up, go back to waiting. */
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Retured due to call to cv_signal() or cv_broadcast(). */
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync rc = VINF_SUCCESS;
4add215f9918fd37934b252922caab7803aaac19vboxsync }
4add215f9918fd37934b252922caab7803aaac19vboxsync else
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* We're being destroyed. */
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = VERR_SEM_DESTROYED;
aaafb754e64fa5946d30a0fa9c1c0ffaa483ee43vboxsync }
4add215f9918fd37934b252922caab7803aaac19vboxsync else if (rc == -1)
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Returned due to timeout being reached. */
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = VERR_TIMEOUT;
a68835e2c9d5426d501f1bc78ff30e8ec5bb12cevboxsync else
4add215f9918fd37934b252922caab7803aaac19vboxsync rc = VERR_INTERRUPTED;
ba2ad20e44479a5831d039c736a0d4ed2aa7d65bvboxsync /* Returned due to pending signal. */
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync break;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync }
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync mutex_exit(&pThis->Mtx);
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync rtR0SemEventMultiSolRelease(pThis);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync return rc;
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncRTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, false /* not interruptible */);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncRTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
089c21a647af46044cad04a78cfdcfae814d2105vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, true /* interruptible */);
089c21a647af46044cad04a78cfdcfae814d2105vboxsync}
089c21a647af46044cad04a78cfdcfae814d2105vboxsync
b9c00cd9c9b5f409e64bd7782815faa2c5ecd85fvboxsync#endif