1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/* $Id$ */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, FreeBSD.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/*
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync *
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Permission is hereby granted, free of charge, to any person
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * obtaining a copy of this software and associated documentation
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * files (the "Software"), to deal in the Software without
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * restriction, including without limitation the rights to use,
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * copies of the Software, and to permit persons to whom the
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Software is furnished to do so, subject to the following
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * conditions:
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync *
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * The above copyright notice and this permission notice shall be
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * included in all copies or substantial portions of the Software.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync *
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * OTHER DEALINGS IN THE SOFTWARE.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/*******************************************************************************
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync* Header Files *
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync*******************************************************************************/
715e49c31b15c23c17a9ce3be42a75e7c48d4b78vboxsync#define RTSEMEVENTMULTI_WITHOUT_REMAPPING
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include "the-freebsd-kernel.h"
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#include "internal/iprt.h"
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include <iprt/semaphore.h>
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include <iprt/assert.h>
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#include <iprt/asm.h>
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include <iprt/err.h>
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#include <iprt/mem.h>
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#include <iprt/lockvalidator.h>
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#include "sleepqueue-r0drv-freebsd.h"
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include "internal/magics.h"
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/*******************************************************************************
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync* Defined Constants And Macros *
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync*******************************************************************************/
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** @name fStateAndGen values
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @{ */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** The state bit number. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#define RTSEMEVENTMULTIBSD_STATE_BIT 0
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** The state mask. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#define RTSEMEVENTMULTIBSD_STATE_MASK RT_BIT_32(RTSEMEVENTMULTIBSD_STATE_BIT)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** The generation mask. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#define RTSEMEVENTMULTIBSD_GEN_MASK ~RTSEMEVENTMULTIBSD_STATE_MASK
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** The generation shift. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#define RTSEMEVENTMULTIBSD_GEN_SHIFT 1
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** The initial variable value. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#define RTSEMEVENTMULTIBSD_STATE_GEN_INIT UINT32_C(0xfffffffc)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/** @} */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/*******************************************************************************
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync* Structures and Typedefs *
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync*******************************************************************************/
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/**
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * FreeBSD multiple release event semaphore.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsynctypedef struct RTSEMEVENTMULTIINTERNAL
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync uint32_t volatile u32Magic;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /** The object state bit and generation counter.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * The generation counter is incremented every time the object is
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * signalled. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync uint32_t volatile fStateAndGen;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /** Reference counter. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync uint32_t volatile cRefs;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
ab93606043a9881487aa83be04191d2f4ea24071vboxsync return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync}
ab93606043a9881487aa83be04191d2f4ea24071vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
ab93606043a9881487aa83be04191d2f4ea24071vboxsync const char *pszNameFmt, ...)
ab93606043a9881487aa83be04191d2f4ea24071vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync PRTSEMEVENTMULTIINTERNAL pThis;
ab93606043a9881487aa83be04191d2f4ea24071vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
ab93606043a9881487aa83be04191d2f4ea24071vboxsync if (pThis)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync pThis->fStateAndGen = RTSEMEVENTMULTIBSD_STATE_GEN_INIT;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync pThis->cRefs = 1;
fea595114d685c0f865a710172df95896f08d47bvboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync *phEventMultiSem = pThis;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VERR_NO_MEMORY;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/**
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Retain a reference to the semaphore.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync *
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @param pThis The semaphore.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncDECLINLINE(void) rtR0SemEventMultiBsdRetain(PRTSEMEVENTMULTIINTERNAL pThis)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync Assert(cRefs && cRefs < 100000);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync}
fea595114d685c0f865a710172df95896f08d47bvboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/**
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Release a reference, destroy the thing if necessary.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync *
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @param pThis The semaphore.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncDECLINLINE(void) rtR0SemEventMultiBsdRelease(PRTSEMEVENTMULTIINTERNAL pThis)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
ab93606043a9881487aa83be04191d2f4ea24071vboxsync RTMemFree(pThis);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync}
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncRTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Validate input.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (pThis == NIL_RTSEMEVENTMULTI)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return VINF_SUCCESS;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync Assert(pThis->cRefs > 0);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Invalidate it and signal the object just in case.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTIBSD_GEN_MASK);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemBsdBroadcast(pThis);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRelease(pThis);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync uint32_t fNew;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync uint32_t fOld;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Validate input.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (!pThis)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return VERR_INVALID_PARAMETER;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRetain(pThis);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Signal the event object. The cause of the parnoia here is racing to try
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * deal with racing RTSemEventMultiSignal calls (should probably be
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * forbidden, but it's relatively easy to handle).
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync do
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync fNew = fOld = ASMAtomicUoReadU32(&pThis->fStateAndGen);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync fNew += 1 << RTSEMEVENTMULTIBSD_GEN_SHIFT;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync fNew |= RTSEMEVENTMULTIBSD_STATE_MASK;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync while (!ASMAtomicCmpXchgU32(&pThis->fStateAndGen, fNew, fOld));
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemBsdBroadcast(pThis);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRelease(pThis);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
ab93606043a9881487aa83be04191d2f4ea24071vboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Validate input.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
ab93606043a9881487aa83be04191d2f4ea24071vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (!pThis)
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return VERR_INVALID_PARAMETER;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRetain(pThis);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Reset it.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTIBSD_STATE_MASK);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRelease(pThis);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync/**
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync *
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @returns VBox status code.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @param pThis The event semaphore.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @param fFlags See RTSemEventMultiWaitEx.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @param uTimeout See RTSemEventMultiWaitEx.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * @param pSrcPos The source code position of the wait.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncstatic int rtR0SemEventMultiBsdWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync PCRTLOCKVALSRCPOS pSrcPos)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync uint32_t fOrgStateAndGen;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync int rc;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Validate the input.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRetain(pThis);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * Is the event already signalled or do we have to wait?
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (fOrgStateAndGen & RTSEMEVENTMULTIBSD_STATE_MASK)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync rc = VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync else
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /*
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync * We have to wait.
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync RTR0SEMBSDSLEEP Wait;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rc = rtR0SemBsdWaitInit(&Wait, fFlags, uTimeout, pThis);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (RT_SUCCESS(rc))
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync for (;;)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /* The destruction test. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rc = VERR_SEM_DESTROYED;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync else
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemBsdWaitPrepare(&Wait);
fea595114d685c0f865a710172df95896f08d47bvboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /* Check the exit conditions. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rc = VERR_SEM_DESTROYED;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
fea595114d685c0f865a710172df95896f08d47bvboxsync rc = VINF_SUCCESS;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync else if (rtR0SemBsdWaitHasTimedOut(&Wait))
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rc = VERR_TIMEOUT;
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync else if (rtR0SemBsdWaitWasInterrupted(&Wait))
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rc = VERR_INTERRUPTED;
fea595114d685c0f865a710172df95896f08d47bvboxsync else
fea595114d685c0f865a710172df95896f08d47bvboxsync {
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync /* Do the wait and then recheck the conditions. */
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemBsdWaitDoIt(&Wait);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync continue;
fea595114d685c0f865a710172df95896f08d47bvboxsync }
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync }
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync break;
fea595114d685c0f865a710172df95896f08d47bvboxsync }
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemBsdWaitDelete(&Wait);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync rtR0SemEventMultiBsdRelease(pThis);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return rc;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncRTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#ifndef RTSEMEVENT_STRICT
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, NULL);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#else
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync#endif
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiWaitEx);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncRTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync RTHCUINTPTR uId, RT_SRC_POS_DECL)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiWaitExDebug);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsyncRTDECL(uint32_t) RTSemEventMultiGetResolution(void)
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync{
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsync return rtR0SemBsdWaitGetResolution();
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync}
9837b5326a44772e824a15f2d5d937ddfd627d54vboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiGetResolution);
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync