29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync/* $Id$ */
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync/** @file
c5b9358e561295f178bc3e0d299bf9c02d357d0evboxsync * IPRT - Single Release Event Semaphores, Ring-0 Driver, Solaris.
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync */
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync *
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync * available from http://www.virtualbox.org. This file is free software;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync * 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.
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync */
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync/*******************************************************************************
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync* Header Files *
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync*******************************************************************************/
715e49c31b15c23c17a9ce3be42a75e7c48d4b78vboxsync#define RTSEMEVENT_WITHOUT_REMAPPING
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync#include "the-solaris-kernel.h"
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync#include "internal/iprt.h"
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync#include <iprt/semaphore.h>
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync#include <iprt/assert.h>
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync#include <iprt/asm.h>
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync# include <iprt/asm-amd64-x86.h>
cbd4e5863be36b70c59ebeb02a611a763f9d58f1vboxsync#endif
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync#include <iprt/err.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/list.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/lockvalidator.h>
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync#include <iprt/mem.h>
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync#include <iprt/mp.h>
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync#include <iprt/thread.h>
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync#include "internal/magics.h"
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include "semeventwait-r0drv-solaris.h"
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync/*******************************************************************************
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync* Structures and Typedefs *
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync*******************************************************************************/
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Waiter entry. Lives on the stack.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @remarks Unfortunately, we cannot easily use cv_signal because we cannot
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * distinguish between it and the spurious wakeups we get after fork.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * So, we keep an unprioritized FIFO with the sleeping threads.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsynctypedef struct RTSEMEVENTSOLENTRY
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** The list node. */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync RTLISTNODE Node;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** The thread. */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync kthread_t *pThread;
4030b8473736055cd02947418ef4f8f9b1945323vboxsync /** Set to @c true when waking up the thread by signal or destroy. */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync uint32_t volatile fWokenUp;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync} RTSEMEVENTSOLENTRY;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/** Pointer to waiter entry. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsynctypedef RTSEMEVENTSOLENTRY *PRTSEMEVENTSOLENTRY;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync/**
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync * Solaris event semaphore.
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync */
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsynctypedef struct RTSEMEVENTINTERNAL
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync{
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync /** Magic value (RTSEMEVENT_MAGIC). */
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync uint32_t volatile u32Magic;
c1a925cf66044662d1265e27eab1337d409f124dvboxsync /** The number of threads referencing this object. */
c1a925cf66044662d1265e27eab1337d409f124dvboxsync uint32_t volatile cRefs;
dc95659cf2f6c5830e66313b6046e4317881035bvboxsync /** Set if the object is signalled when there are no waiters. */
dc95659cf2f6c5830e66313b6046e4317881035bvboxsync bool fSignaled;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** List of waiting and woken up threads. */
e961f5bfe1727c6816d3dad3805ebe21b6ba1c64vboxsync RTLISTANCHOR WaitList;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync /** The Solaris mutex protecting this structure and pairing up the with the cv. */
b34f0f200ed0778053a2a1d93381c2c6b60cb2d5vboxsync kmutex_t Mtx;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync /** The Solaris condition variable. */
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync kcondvar_t Cnd;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsyncRTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync{
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync}
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsyncRTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync{
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync AssertPtrReturn(phEventSem, VERR_INVALID_POINTER);
9c11b89c71ca727d975c39f2719063501ddcd03dvboxsync RT_ASSERT_PREEMPTIBLE();
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync if (!pThis)
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync return VERR_NO_MEMORY;
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync
c1a925cf66044662d1265e27eab1337d409f124dvboxsync pThis->u32Magic = RTSEMEVENT_MAGIC;
dc95659cf2f6c5830e66313b6046e4317881035bvboxsync pThis->cRefs = 1;
dc95659cf2f6c5830e66313b6046e4317881035bvboxsync pThis->fSignaled = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTListInit(&pThis->WaitList);
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync *phEventSem = pThis;
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync return VINF_SUCCESS;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync}
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Retain a reference to the semaphore.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pThis The semaphore.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(void) rtR0SemEventSolRetain(PRTSEMEVENTINTERNAL pThis)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync Assert(cRefs && cRefs < 100000);
175770d4533d92ff4ef576d5ea97e566cc488472vboxsync NOREF(cRefs);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * The destruct.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pThis The semaphore.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncstatic void rtR0SemEventSolDtor(PRTSEMEVENTINTERNAL pThis)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync Assert(pThis->u32Magic != RTSEMEVENT_MAGIC);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync cv_destroy(&pThis->Cnd);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync mutex_destroy(&pThis->Mtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTMemFree(pThis);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Release a reference, destroy the thing if necessary.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pThis The semaphore.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(void) rtR0SemEventSolRelease(PRTSEMEVENTINTERNAL pThis)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemEventSolDtor(pThis);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsyncRTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Validate input.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync PRTSEMEVENTINTERNAL pThis = hEventSem;
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync if (pThis == NIL_RTSEMEVENT)
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync return VINF_SUCCESS;
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync Assert(pThis->cRefs > 0);
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync RT_ASSERT_INTS_ON();
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync mutex_enter(&pThis->Mtx);
d66f73c3fe5c4de905e6b8623d2d3fe170628358vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Invalidate the semaphore.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ASMAtomicWriteBool(&pThis->fSignaled, false);
d66f73c3fe5c4de905e6b8623d2d3fe170628358vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Abort and wake up all threads.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync PRTSEMEVENTSOLENTRY pWaiter;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node)
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWaiter->fWokenUp = true;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync cv_broadcast(&pThis->Cnd);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Release the reference from RTSemEventCreateEx.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync mutex_exit(&pThis->Mtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemEventSolRelease(pThis);
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync return VINF_SUCCESS;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync}
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncRTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync{
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync RT_ASSERT_PREEMPT_CPUID_VAR();
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync RT_ASSERT_INTS_ON();
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemEventSolRetain(pThis);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Wake up one thread.
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ASMAtomicWriteBool(&pThis->fSignaled, true);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync PRTSEMEVENTSOLENTRY pWaiter;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node)
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (!pWaiter->fWokenUp)
542b82b1871753dc94a2a17b504094112f9df306vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWaiter->fWokenUp = true;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync setrun(pWaiter->pThread);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ASMAtomicWriteBool(&pThis->fSignaled, false);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync break;
542b82b1871753dc94a2a17b504094112f9df306vboxsync }
69dc0354ae98899256f5e73898f1dc973345ee65vboxsync }
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync mutex_exit(&pThis->Mtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemEventSolRelease(pThis);
2ee7a36e525389d535649872c492332c9d92b139vboxsync
858960add9f9dc845ad839300639ca2d932a1715vboxsync#ifdef DEBUG_ramshankar
858960add9f9dc845ad839300639ca2d932a1715vboxsync /** See @bugref{6318} comment#11 */
858960add9f9dc845ad839300639ca2d932a1715vboxsync return VINF_SUCCESS;
858960add9f9dc845ad839300639ca2d932a1715vboxsync#endif
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync RT_ASSERT_PREEMPT_CPUID();
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync return VINF_SUCCESS;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync}
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
8c99dcd207cf5b7bee01f95fbe19728a94076f94vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @returns VBox status code.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pThis The event semaphore.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param fFlags See RTSemEventWaitEx.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param uTimeout See RTSemEventWaitEx.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pSrcPos The source code position of the wait.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncstatic int rtR0SemEventSolWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
3bad884471a4755d52abffc98cc326f153750ca1vboxsync PCRTLOCKVALSRCPOS pSrcPos)
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync{
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Validate the input.
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemEventSolRetain(pThis);
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync mutex_enter(&pThis->Mtx);
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * In the signaled state?
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync int rc;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (ASMAtomicCmpXchgBool(&pThis->fSignaled, false, true))
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync rc = VINF_SUCCESS;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync else
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * We have to wait.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTR0SEMSOLWAIT Wait;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rc = rtR0SemSolWaitInit(&Wait, fFlags, uTimeout);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (RT_SUCCESS(rc))
56665b35e85d3cd7d4232957d09b488ab44d81cfvboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync RTSEMEVENTSOLENTRY Waiter; /* ASSUMES we won't get swapped out while waiting (TS_DONT_SWAP). */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync Waiter.pThread = curthread;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync Waiter.fWokenUp = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTListAppend(&pThis->WaitList, &Waiter.Node);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync for (;;)
56665b35e85d3cd7d4232957d09b488ab44d81cfvboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /* The destruction test. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rc = VERR_SEM_DESTROYED;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /* Check the exit conditions. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rc = VERR_SEM_DESTROYED;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else if (Waiter.fWokenUp)
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync rc = VINF_SUCCESS;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else if (rtR0SemSolWaitHasTimedOut(&Wait))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rc = VERR_TIMEOUT;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else if (rtR0SemSolWaitWasInterrupted(&Wait))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rc = VERR_INTERRUPTED;
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /* Do the wait and then recheck the conditions. */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx, &Waiter.fWokenUp, false);
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync continue;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
0e7d0c39cbbe71e242bb3c9376a736f6169b7efbvboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync break;
56665b35e85d3cd7d4232957d09b488ab44d81cfvboxsync }
dc95659cf2f6c5830e66313b6046e4317881035bvboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemSolWaitDelete(&Wait);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTListNodeRemove(&Waiter.Node);
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync }
d66f73c3fe5c4de905e6b8623d2d3fe170628358vboxsync }
d66f73c3fe5c4de905e6b8623d2d3fe170628358vboxsync
a734bb626f889ee3334bfc381be194b4ec56aae6vboxsync mutex_exit(&pThis->Mtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rtR0SemEventSolRelease(pThis);
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync return rc;
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync}
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
29bdc01040c07a3dd482a94a2cb8f0a90f8587a7vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncRTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
727cf0d6c794dffee1023d2bbb6e94eda7f35ca9vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#ifndef RTSEMEVENT_STRICT
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, NULL);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, &SrcPos);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#endif
727cf0d6c794dffee1023d2bbb6e94eda7f35ca9vboxsync}
727cf0d6c794dffee1023d2bbb6e94eda7f35ca9vboxsync
727cf0d6c794dffee1023d2bbb6e94eda7f35ca9vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncRTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTHCUINTPTR uId, RT_SRC_POS_DECL)
727cf0d6c794dffee1023d2bbb6e94eda7f35ca9vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, &SrcPos);
727cf0d6c794dffee1023d2bbb6e94eda7f35ca9vboxsync}
c1a925cf66044662d1265e27eab1337d409f124dvboxsync
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsyncRTDECL(uint32_t) RTSemEventGetResolution(void)
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync{
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync return rtR0SemSolWaitGetResolution();
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync}
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync