semevent-r0drv-solaris.c revision e0e7da0420be1398d23ffa9953686d3a43619abd
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync/* $Id$ */
332d68e9666b04a5aa788a586d9f4c6b1f19c700vboxsync/** @file
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * IPRT - Single Release Event Semaphores, Ring-0 Driver, Solaris.
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync */
332d68e9666b04a5aa788a586d9f4c6b1f19c700vboxsync
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync/*
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * Copyright (C) 2006-2010 Oracle Corporation
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync *
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * available from http://www.virtualbox.org. This file is free software;
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * General Public License (GPL) as published by the Free Software
9496b6f77d66eb89f088668752b8838d578d6e10vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * CDDL are applicable instead of those of the GPL.
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync *
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync * You may elect to license modified versions of this file under the
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync * terms and conditions of either the GPL or the CDDL or both.
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync */
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync/*******************************************************************************
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync* Header Files *
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync*******************************************************************************/
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include "the-solaris-kernel.h"
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include "internal/iprt.h"
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/semaphore.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/assert.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/asm.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync# include <iprt/asm-amd64-x86.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#endif
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/err.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/list.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/lockvalidator.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/mem.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/mp.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include <iprt/thread.h>
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include "internal/magics.h"
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync#include "semeventwait-r0drv-solaris.h"
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync/*******************************************************************************
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync* Structures and Typedefs *
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync*******************************************************************************/
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync/**
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * Waiter entry. Lives on the stack.
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync *
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * @remarks Unfortunately, we cannot easily use cv_signal because we cannot
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync * distinguish between it and the spurious wakeups we get after fork.
9a08dd6ed47cffa9cacbb9d53db1ce71d04db61fvboxsync * So, we keep an unprioritized FIFO with the sleeping threads.
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsynctypedef struct RTSEMEVENTSOLENTRY
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync{
9a08dd6ed47cffa9cacbb9d53db1ce71d04db61fvboxsync /** The list node. */
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync RTLISTNODE Node;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** The thread. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync kthread_t *pThread;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** Flag set when waking up the thread by signal or destroy. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync bool volatile fWokenUp;
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync} RTSEMEVENTSOLENTRY;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync/** Pointer to waiter entry. */
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsynctypedef RTSEMEVENTSOLENTRY *PRTSEMEVENTSOLENTRY;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync
b459362b1c9b5ce5e6bf4ceb32ffe1294c08be07vboxsync
b459362b1c9b5ce5e6bf4ceb32ffe1294c08be07vboxsync/**
b459362b1c9b5ce5e6bf4ceb32ffe1294c08be07vboxsync * Solaris event semaphore.
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync */
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsynctypedef struct RTSEMEVENTINTERNAL
b459362b1c9b5ce5e6bf4ceb32ffe1294c08be07vboxsync{
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync /** Magic value (RTSEMEVENT_MAGIC). */
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync uint32_t volatile u32Magic;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync /** The number of threads referencing this object. */
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync uint32_t volatile cRefs;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** Set if the object is signalled when there are no waiters. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync bool fSignaled;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** List of waiting and woken up threads. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync RTLISTNODE WaitList;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** The Solaris mutex protecting this structure and pairing up the with the cv. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync kmutex_t Mtx;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync /** The Solaris condition variable. */
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync kcondvar_t Cnd;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsync
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync
0c8b774aca1168c2007424a49f6fa159fc23e42bvboxsyncRTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
f4ccb18a71e0e531719734918583f84fbc72ebfevboxsync{
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
cfd41a3683178a30bac4417128b4673806653797vboxsync}
cfd41a3683178a30bac4417128b4673806653797vboxsync
cfd41a3683178a30bac4417128b4673806653797vboxsync
cfd41a3683178a30bac4417128b4673806653797vboxsyncRTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
cfd41a3683178a30bac4417128b4673806653797vboxsync{
cfd41a3683178a30bac4417128b4673806653797vboxsync AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
cfd41a3683178a30bac4417128b4673806653797vboxsync AssertReturn(!(fFlags & ~RTSEMEVENT_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
cfd41a3683178a30bac4417128b4673806653797vboxsync AssertPtrReturn(phEventSem, VERR_INVALID_POINTER);
cfd41a3683178a30bac4417128b4673806653797vboxsync RT_ASSERT_PREEMPTIBLE();
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (!pThis)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync return VERR_NO_MEMORY;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync pThis->u32Magic = RTSEMEVENT_MAGIC;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync pThis->cRefs = 1;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync pThis->fSignaled = false;
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync RTListInit(&pThis->WaitList);
613c0d015cbaef93be47fc03f0708744c5c24f79vboxsync mutex_init(&pThis->Mtx, "IPRT Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
9a1578b66f9e563cf99c75ffa881db476f477e3avboxsync cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync *phEventSem = pThis;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync return VINF_SUCCESS;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync}
b8b61ff747c97d77b48c572a474969b1892d591dvboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync/**
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * Retain a reference to the semaphore.
907ba2c9b3d1821f95be17115ecad9fe8a2cae02vboxsync *
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pThis The semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncDECLINLINE(void) rtR0SemEventSolRetain(PRTSEMEVENTINTERNAL pThis)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync{
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync Assert(cRefs && cRefs < 100000);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync}
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync
f6cc81e94c29cc9b39b896cf32ecfe0501b4a1e5vboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync/**
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * The destruct.
efbdd9fc22305720d20be7cc37b4f45f43146b09vboxsync *
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync * @param pThis The semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncstatic void rtR0SemEventSolDtor(PRTSEMEVENTINTERNAL pThis)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync{
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync Assert(pThis->u32Magic != RTSEMEVENT_MAGIC);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync cv_destroy(&pThis->Cnd);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync mutex_destroy(&pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RTMemFree(pThis);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync}
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync/**
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync * Release a reference, destroy the thing if necessary.
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync *
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pThis The semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncDECLINLINE(void) rtR0SemEventSolRelease(PRTSEMEVENTINTERNAL pThis)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync{
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemEventSolDtor(pThis);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync}
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncRTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync{
9c59bcefe2993070fafaf0d6cee9673f48479128vboxsync /*
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Validate input.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTINTERNAL pThis = hEventSem;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (pThis == NIL_RTSEMEVENT)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync return VINF_SUCCESS;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync Assert(pThis->cRefs > 0);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RT_ASSERT_INTS_ON();
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync mutex_enter(&pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /*
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Invalidate the semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync ASMAtomicWriteBool(&pThis->fSignaled, false);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /*
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Abort and wake up all threads.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTSOLENTRY pWaiter;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync {
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync pWaiter->fWokenUp = true;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync }
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync cv_broadcast(&pThis->Cnd);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /*
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Release the reference from RTSemEventCreateEx.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync mutex_exit(&pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemEventSolRelease(pThis);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync return VINF_SUCCESS;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync}
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncRTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync{
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RT_ASSERT_PREEMPT_CPUID_VAR();
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RT_ASSERT_INTS_ON();
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemEventSolRetain(pThis);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /*
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Wake up one thread.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync ASMAtomicWriteBool(&pThis->fSignaled, true);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PRTSEMEVENTSOLENTRY pWaiter;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RTListForEach(&pThis->WaitList, pWaiter, RTSEMEVENTSOLENTRY, Node)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync {
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (!pWaiter->fWokenUp)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync {
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync pWaiter->fWokenUp = true;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync setrun(pWaiter->pThread);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync ASMAtomicWriteBool(&pThis->fSignaled, false);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync break;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync }
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync }
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync mutex_exit(&pThis->Mtx);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemEventSolRelease(pThis);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync RT_ASSERT_PREEMPT_CPUID();
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync return VINF_SUCCESS;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync}
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync/**
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync *
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @returns VBox status code.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pThis The event semaphore.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param fFlags See RTSemEventWaitEx.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param uTimeout See RTSemEventWaitEx.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * @param pSrcPos The source code position of the wait.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncstatic int rtR0SemEventSolWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync PCRTLOCKVALSRCPOS pSrcPos)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync{
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /*
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync * Validate the input.
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync rtR0SemEventSolRetain(pThis);
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync mutex_enter(&pThis->Mtx);
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync /*
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync * In the signaled state?
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync */
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync int rc;
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync if (ASMAtomicCmpXchgBool(&pThis->fSignaled, false, true))
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync rc = VINF_SUCCESS;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync else
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync {
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync /*
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync * We have to wait.
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync */
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync RTR0SEMSOLWAIT Wait;
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync rc = rtR0SemSolWaitInit(&Wait, fFlags, uTimeout);
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync if (RT_SUCCESS(rc))
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync {
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync RTSEMEVENTSOLENTRY Waiter; /* ASSUMES we won't get swapped out while waiting (TS_DONT_SWAP). */
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync Waiter.pThread = curthread;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync Waiter.fWokenUp = false;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync RTListAppend(&pThis->WaitList, &Waiter.Node);
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync for (;;)
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync {
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync /* The destruction test. */
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
1d258b8772ee104b5fab3d1743eabc2f5cfe2fa4vboxsync rc = VERR_SEM_DESTROYED;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync else
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync {
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /* Check the exit conditions. */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rc = VERR_SEM_DESTROYED;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync else if (Waiter.fWokenUp)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rc = VINF_SUCCESS;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync else if (rtR0SemSolWaitHasTimedOut(&Wait))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rc = VERR_TIMEOUT;
53e1c27c7564c45ad0b92676ddea561591a3e869vboxsync else if (rtR0SemSolWaitWasInterrupted(&Wait))
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rc = VERR_INTERRUPTED;
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync else
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync {
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync /* Do the wait and then recheck the conditions. */
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx);
6e3cc82d5d5effda92c9fec18b870d54386f99favboxsync continue;
6e3cc82d5d5effda92c9fec18b870d54386f99favboxsync }
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync }
771761cda2c81e899526a0dce22c8cd2510fff82vboxsync break;
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync }
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync
9ced981a0263f6280ccbf5dc64c0e81fbe4a2fdavboxsync rtR0SemSolWaitDelete(&Wait);
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync RTListNodeRemove(&Waiter.Node);
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync }
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync }
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync mutex_exit(&pThis->Mtx);
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync rtR0SemEventSolRelease(pThis);
59816992ec770eb9c03fbc1233ae62114a026badvboxsync return rc;
9a1578b66f9e563cf99c75ffa881db476f477e3avboxsync}
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync
97674677e4f2aeae576c39f966568dd664ba7979vboxsync
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync#undef RTSemEventWaitEx
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsyncRTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
77c85c820fe4467a0856134e0c9e5c5790cd847evboxsync{
72f66530e1bf87aa6894a5f55f1b4d36caa5761fvboxsync#ifndef RTSEMEVENT_STRICT
97674677e4f2aeae576c39f966568dd664ba7979vboxsync return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, NULL);
97674677e4f2aeae576c39f966568dd664ba7979vboxsync#else
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, &SrcPos);
#endif
}
RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
RTHCUINTPTR uId, RT_SRC_POS_DECL)
{
RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
return rtR0SemEventSolWait(hEventSem, fFlags, uTimeout, &SrcPos);
}
RTDECL(uint32_t) RTSemEventGetResolution(void)
{
return rtR0SemSolWaitGetResolution();
}