semeventmulti-r0drv-linux.c revision 683eff3070b1b86fe71b71af7fda82766ea19d17
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/* $Id$ */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** @file
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Linux.
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2010 Oracle Corporation
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync *
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * available from http://www.virtualbox.org. This file is free software;
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * General Public License (GPL) as published by the Free Software
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync *
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * The contents of this file may alternatively be used under the terms
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync * of the Common Development and Distribution License Version 1.0
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync * CDDL are applicable instead of those of the GPL.
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync *
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync * You may elect to license modified versions of this file under the
1ce069685b24d243eb0464f46d4c56b250c64445vboxsync * terms and conditions of either the GPL or the CDDL or both.
a55af63ead2dcca370bfc0dfe49771d9dcc61b93vboxsync */
e0778e583cb4a0bdc9bcc48f5957e00a01108388vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
a55af63ead2dcca370bfc0dfe49771d9dcc61b93vboxsync/*******************************************************************************
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync* Header Files *
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync*******************************************************************************/
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync#include "the-linux-kernel.h"
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include "internal/iprt.h"
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include <iprt/semaphore.h>
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include <iprt/assert.h>
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include <iprt/asm.h>
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include <iprt/err.h>
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include <iprt/mem.h>
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync#include <iprt/lockvalidator.h>
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync#include "waitqueue-r0drv-linux.h"
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync#include "internal/magics.h"
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync/*******************************************************************************
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync* Defined Constants And Macros *
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync*******************************************************************************/
b0ad0bbadf3a5b5258acda1bfe16f0ad8bee5ff0vboxsync/** @name fStateAndGen values
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync * @{ */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** The state bit number. */
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync#define RTSEMEVENTMULTILNX_STATE_BIT 0
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** The state mask. */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync#define RTSEMEVENTMULTILNX_STATE_MASK RT_BIT_32(RTSEMEVENTMULTILNX_STATE_BIT)
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** The generation mask. */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync#define RTSEMEVENTMULTILNX_GEN_MASK ~RTSEMEVENTMULTILNX_STATE_MASK
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** The generation shift. */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync#define RTSEMEVENTMULTILNX_GEN_SHIFT 1
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** The initial variable value. */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync#define RTSEMEVENTMULTILNX_STATE_GEN_INIT UINT32_C(0xfffffffc)
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/** @} */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/*******************************************************************************
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync* Structures and Typedefs *
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync*******************************************************************************/
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync/**
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * Linux event semaphore.
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync */
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsynctypedef struct RTSEMEVENTMULTIINTERNAL
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync{
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync /** Magic value (RTSEMEVENTMULTI_MAGIC). */
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync uint32_t volatile u32Magic;
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /** The object state bit and generation counter.
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * The generation counter is incremented every time the object is */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync uint32_t volatile fStateAndGen;
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /** Reference counter. */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync uint32_t volatile cRefs;
a2d9f81753c129b5e3bbe3769627dcd25a3724bdvboxsync /** The wait queue. */
a2d9f81753c129b5e3bbe3769627dcd25a3724bdvboxsync wait_queue_head_t Head;
a2d9f81753c129b5e3bbe3769627dcd25a3724bdvboxsync} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
a2d9f81753c129b5e3bbe3769627dcd25a3724bdvboxsync
a2d9f81753c129b5e3bbe3769627dcd25a3724bdvboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsyncRTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync{
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync}
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
a2d9f81753c129b5e3bbe3769627dcd25a3724bdvboxsyncRTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync const char *pszNameFmt, ...)
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync{
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync PRTSEMEVENTMULTIINTERNAL pThis;
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync if (pThis)
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync {
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync pThis->fStateAndGen = RTSEMEVENTMULTILNX_STATE_GEN_INIT;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync pThis->cRefs = 1;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync init_waitqueue_head(&pThis->Head);
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync *phEventMultiSem = pThis;
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync return VINF_SUCCESS;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync }
7bf07b1592dfaab1a4fb6d497fd0ff1302fb7585vboxsync return VERR_NO_MEMORY;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
7c1f498692cd2393f8ba68cb62be482495106f93vboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiCreate);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
7c1f498692cd2393f8ba68cb62be482495106f93vboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync/**
4c8907a420ed66a42f729eb08cddf9c1e57f25eavboxsync * Retain a reference to the semaphore.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync *
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * @param pThis The semaphore.
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync */
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsyncDECLINLINE(void) rtR0SemEventMultiLnxRetain(PRTSEMEVENTMULTIINTERNAL pThis)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync{
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync Assert(cRefs && cRefs < 100000);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync/**
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Release a reference, destroy the thing if necessary.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync *
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * @param pThis The semaphore.
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync */
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsyncDECLINLINE(void) rtR0SemEventMultiLnxRelease(PRTSEMEVENTMULTIINTERNAL pThis)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync{
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync {
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync RTMemFree(pThis);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync }
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncRTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync{
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /*
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * Validate input.
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync */
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync if (pThis == NIL_RTSEMEVENTMULTI)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync return VINF_SUCCESS;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync Assert(pThis->cRefs > 0);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync /*
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Invalidate it and signal the object just in case.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTILNX_GEN_MASK);
85bc82f92f4d7a7b95e96d133c4847b2847703dfvboxsync Assert(!waitqueue_active(&pThis->Head));
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync wake_up_all(&pThis->Head);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync return VINF_SUCCESS;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiDestroy);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync{
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync uint32_t fNew;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync uint32_t fOld;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync /*
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync * Validate input.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync if (!pThis)
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync return VERR_INVALID_PARAMETER;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync rtR0SemEventMultiLnxRetain(pThis);
7a29aa5ce149ccd344a2929d2815b8e212690b92vboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync /*
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Signal the event object. The cause of the parnoia here is racing to try
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * deal with racing RTSemEventMultiSignal calls (should probably be
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * forbidden, but it's relatively easy to handle).
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync do
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync {
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync fNew = fOld = ASMAtomicUoReadU32(&pThis->fStateAndGen);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync fNew += 1 << RTSEMEVENTMULTILNX_GEN_SHIFT;
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync fNew |= RTSEMEVENTMULTILNX_STATE_MASK;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync }
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync while (!ASMAtomicCmpXchgU32(&pThis->fStateAndGen, fNew, fOld));
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync wake_up_all(&pThis->Head);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync rtR0SemEventMultiLnxRelease(pThis);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync return VINF_SUCCESS;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiSignal);
5453eb2f2719bf3895ac3daeec4c26e0b6e2eb4avboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
9bb98d54790a98dad0ad6d9bdc5d319b6fdf0bffvboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync{
9bb98d54790a98dad0ad6d9bdc5d319b6fdf0bffvboxsync /*
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Validate input.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync if (!pThis)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync return VERR_INVALID_PARAMETER;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
629e8f58c569e4c51a98284c41754fd9f0b973f8vboxsync rtR0SemEventMultiLnxRetain(pThis);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
7c1f498692cd2393f8ba68cb62be482495106f93vboxsync /*
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Reset it.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTILNX_STATE_MASK);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
8c58249d7f93d82395aa6c8b31526443892bc375vboxsync rtR0SemEventMultiLnxRelease(pThis);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync return VINF_SUCCESS;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiReset);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync/**
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync *
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * @returns VBox status code.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * @param pThis The event semaphore.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * @param fFlags See RTSemEventMultiWaitEx.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * @param uTimeout See RTSemEventMultiWaitEx.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * @param pSrcPos The source code position of the wait.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncstatic int rtR0SemEventMultiLnxWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync PCRTLOCKVALSRCPOS pSrcPos)
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync{
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync uint32_t fOrgStateAndGen;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync int rc;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync /*
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Validate the input.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync rtR0SemEventMultiLnxRetain(pThis);
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /*
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync * Is the event already signalled or do we have to wait?
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync */
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync if (fOrgStateAndGen & RTSEMEVENTMULTILNX_STATE_MASK)
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync rc = VINF_SUCCESS;
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync else
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync {
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /*
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync * We have to wait.
5704a317c3b6bdf4b59f6a6ebe45d443296b1995vboxsync */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync RTR0SEMLNXWAIT Wait;
5704a317c3b6bdf4b59f6a6ebe45d443296b1995vboxsync rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync if (RT_SUCCESS(rc))
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync {
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync IPRT_DEBUG_SEMS_STATE(pThis, 'E');
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync for (;;)
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync {
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /* The destruction test. */
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync rc = VERR_SEM_DESTROYED;
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync else
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync {
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync rtR0SemLnxWaitPrepare(&Wait);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync /* Check the exit conditions. */
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
a0644dbbd30adb9bd2937110d6f016e56c4cc52bvboxsync rc = VERR_SEM_DESTROYED;
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync rc = VINF_SUCCESS;
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync else if (rtR0SemLnxWaitHasTimedOut(&Wait))
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync rc = VERR_TIMEOUT;
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync else if (rtR0SemLnxWaitWasInterrupted(&Wait))
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync rc = VERR_INTERRUPTED;
229a63857c5fd2e441a62206eacce4156d0b2a26vboxsync else
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync {
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync /* Do the wait and then recheck the conditions. */
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync rtR0SemLnxWaitDoIt(&Wait);
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync continue;
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync }
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync }
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync break;
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync }
2711c80499bbd95e3da4a6cd2dffd9f81a5dce98vboxsync
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync rtR0SemLnxWaitDelete(&Wait);
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync }
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync }
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
cc74f15083bf80fbc96723a89faa06c15d0dead8vboxsync rtR0SemEventMultiLnxRelease(pThis);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return rc;
9ca017ceee656f9d33f2cb6652e401b5f17fcfb7vboxsync}
cc74f15083bf80fbc96723a89faa06c15d0dead8vboxsync
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync#undef RTSemEventMultiWaitEx
3933885bc0c2c93436d858a14564c6179ec72872vboxsyncRTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
6e25221ce8ef8e656d1e15eb7ec5cf8ae758ceb2vboxsync{
3933885bc0c2c93436d858a14564c6179ec72872vboxsync#ifndef RTSEMEVENT_STRICT
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, NULL);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync#else
3933885bc0c2c93436d858a14564c6179ec72872vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
824ae3158a8b8f8233fec3f5a12c81f139933698vboxsync return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync#endif
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync}
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiWaitEx);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncRTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync RTHCUINTPTR uId, RT_SRC_POS_DECL)
80b09746c07120c881b61b18f30c9c4a2a4af9c5vboxsync{
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
80b09746c07120c881b61b18f30c9c4a2a4af9c5vboxsync}
d7c2269005543188a6fb12775f6d416431e39ebcvboxsyncRT_EXPORT_SYMBOL(RTSemEventMultiWaitExDebug);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync