PDMAllCritSectRw.cpp revision 1e492a1641955148d5024f44aa35a2084bcc47d3
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/* $Id$ */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** @file
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * IPRT - Read/Write Critical Section, Generic.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Copyright (C) 2009-2013 Oracle Corporation
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * available from http://www.virtualbox.org. This file is free software;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * General Public License (GPL) as published by the Free Software
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/*******************************************************************************
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync* Header Files *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync*******************************************************************************/
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define LOG_GROUP LOG_GROUP_PDM//_CRITSECT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include "PDMInternal.h"
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/vmm/pdmcritsectrw.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/vmm/mm.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/vmm/vmm.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/vmm/vm.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/err.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/vmm/hm.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <VBox/log.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <iprt/asm.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <iprt/asm-amd64-x86.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#include <iprt/assert.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef IN_RING3
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync# include <iprt/lockvalidator.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync# include <iprt/semaphore.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#if defined(IN_RING3) || defined(IN_RING0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync# include <iprt/thread.h>
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/*******************************************************************************
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync* Defined Constants And Macros *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync*******************************************************************************/
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** The number loops to spin for shared access in ring-3. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define PDMCRITSECTRW_SHRD_SPIN_COUNT_R3 20
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** The number loops to spin for shared access in ring-0. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define PDMCRITSECTRW_SHRD_SPIN_COUNT_R0 128
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** The number loops to spin for shared access in the raw-mode context. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define PDMCRITSECTRW_SHRD_SPIN_COUNT_RC 128
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** The number loops to spin for exclusive access in ring-3. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define PDMCRITSECTRW_EXCL_SPIN_COUNT_R3 20
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** The number loops to spin for exclusive access in ring-0. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define PDMCRITSECTRW_EXCL_SPIN_COUNT_R0 256
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/** The number loops to spin for exclusive access in the raw-mode context. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#define PDMCRITSECTRW_EXCL_SPIN_COUNT_RC 256
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/* Undefine the automatic VBOX_STRICT API mappings. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#undef PDMCritSectRwEnterExcl
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#undef PDMCritSectRwTryEnterExcl
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#undef PDMCritSectRwEnterShared
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#undef PDMCritSectRwTryEnterShared
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Gets the ring-3 native thread handle of the calling thread.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns native thread handle (ring-3).
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis The read/write critical section. This is only used in
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * R0 and RC.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncDECL_FORCE_INLINE(RTNATIVETHREAD) pdmCritSectRwGetNativeSelf(PCPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef IN_RING3
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync NOREF(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertMsgReturn(pThis->s.Core.u32Magic == RTCRITSECT_MAGIC, ("%RX32\n", pThis->s.Core.u32Magic),
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync NIL_RTNATIVETHREAD);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync PVM pVM = pThis->s.CTX_SUFF(pVM); AssertPtr(pVM);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync PVMCPU pVCpu = VMMGetCpu(pVM); AssertPtr(pVCpu);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeSelf = pVCpu->hNativeThread; Assert(hNativeSelf != NIL_RTNATIVETHREAD);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return hNativeSelf;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef IN_RING3
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Changes the lock validator sub-class of the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * It is recommended to try make sure that nobody is using this critical section
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * while changing the value.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * lock validator isn't compiled in or either of the parameters are
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * invalid.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uSubClass The new sub-class value.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(uint32_t) PDMR3CritSectRwSetSubClass(PPDMCRITSECTRW pThis, uint32_t uSubClass)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync# ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(!(pThis->s.Core.fFlags & RTCRITSECT_FLAGS_NOP), RTLOCKVAL_SUB_CLASS_INVALID);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLockValidatorRecSharedSetSubClass(pThis->s.Core.pValidatorRead, uSubClass);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return RTLockValidatorRecExclSetSubClass(pThis->s.Core.pValidatorWrite, uSubClass);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync# else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync NOREF(uSubClass);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return RTLOCKVAL_SUB_CLASS_INVALID;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync# endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif /* IN_RING3 */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncstatic int pdmCritSectRwEnterShared(PPDMCRITSECTRW pThis, int rcBusy, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate input.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (!fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (hNativeWriter != NIL_RTTHREAD && hNativeWriter == pdmCritSectRwGetNativeSelf(pThis))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc9 = RTLockValidatorRecExclCheckOrder(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc9 = RTLockValidatorRecSharedCheckOrder(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Get cracking...
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* It flows in the right direction, try follow it before it changes. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c++;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_CNT_RD_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= c << RTCSRW_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLockValidatorRecSharedAddOwner(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else if ((u64State & (RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK)) == 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Wrong direction, but we're alone here and can simply try switch the direction. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= (UINT64_C(1) << RTCSRW_CNT_RD_SHIFT) | (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(!pThis->s.Core.fNeedReset);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLockValidatorRecSharedAddOwner(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Is the writer perhaps doing a read recursion? */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (hNativeSelf == hNativeWriter)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9 = RTLockValidatorRecExclRecursionMixed(pThis->s.Core.pValidatorWrite, &pThis->s.Core.pValidatorRead->Core, pSrcPos);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(pThis->s.Core.cWriterReads < UINT32_MAX / 2);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicIncU32(&pThis->s.Core.cWriterReads);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VINF_SUCCESS; /* don't break! */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* If we're only trying, return already. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_BUSY;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Add ourselves to the queue and wait for the direction to change. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c++;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync cWait++;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(cWait <= c);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(cWait < RTCSRW_CNT_MASK / 2);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (uint32_t iLoop = 0; ; iLoop++)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc = RTLockValidatorRecSharedCheckBlocking(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos, true,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_READ, false);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_SUCCESS(rc))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTTHREAD hThreadSelf = RTThreadSelf();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_READ, false);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync do
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc = SUPSemEventMultiWaitNoResume(pThis->s.CTX_SUFF(pVM)->pSession,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RT_INDEFINITE_WAIT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync while (rc == VERR_INTERRUPTED && pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_DESTROYED;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Decrement the counts and return the error. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64OldState = u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT; Assert(c > 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c--;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT; Assert(cWait > 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync cWait--;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(pThis->s.Core.fNeedReset);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertMsg(iLoop < 1, ("%u\n", iLoop));
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Decrement the wait count and maybe reset the semaphore (if we're last). */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(cWait > 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync cWait--;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_WAIT_CNT_RD_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= cWait << RTCSRW_WAIT_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (cWait == 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicXchgBool(&pThis->s.Core.fNeedReset, false))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc = SUPSemEventMultiReset(pThis->s.CTX_SUFF(pVM)->pSession,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertRCReturn(rc, rc);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLockValidatorRecSharedAddOwner(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_DESTROYED;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMNopPause();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* got it! */
1e492a1641955148d5024f44aa35a2084bcc47d3vboxsync STAM_REL_COUNTER_INC(&pThis->s.CTX_MID_Z(Stat,EnterShared));
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert((ASMAtomicReadU64(&pThis->s.Core.u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT));
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VINF_SUCCESS;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Enter a critical section with shared (read) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @a rcBusy if in ring-0 or raw-mode context and it is busy.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param rcBusy The status code to return when we're in RC or R0 and the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * section is busy. Pass VINF_SUCCESS to acquired the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * critical section thru a ring-3 call if necessary.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uId Where we're entering the section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFile The source position - file.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param iLine The source position - line.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFunction The source position - function.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwEnterSharedDebug, PDMCritSectRwTryEnterShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwTryEnterSharedDebug, PDMCritSectRwLeaveShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwEnterShared.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwEnterShared(PPDMCRITSECTRW pThis, int rcBusy)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifndef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterShared(pThis, rcBusy, NULL, false /*fTryOnly*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterShared(pThis, rcBusy, &SrcPos, false /*fTryOnly*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Enter a critical section with shared (read) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @a rcBusy if in ring-0 or raw-mode context and it is busy.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param rcBusy The status code to return when we're in RC or R0 and the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * section is busy. Pass VINF_SUCCESS to acquired the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * critical section thru a ring-3 call if necessary.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uId Where we're entering the section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFile The source position - file.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param iLine The source position - line.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFunction The source position - function.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwEnterShared, PDMCritSectRwTryEnterShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwTryEnterSharedDebug, PDMCritSectRwLeaveShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwEnterSharedDebug.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwEnterSharedDebug(PPDMCRITSECTRW pThis, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterShared(pThis, rcBusy, &SrcPos, false /*fTryOnly*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Try enter a critical section with shared (read) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uId Where we're entering the section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFile The source position - file.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param iLine The source position - line.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFunction The source position - function.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwTryEnterSharedDebug, PDMCritSectRwEnterShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwEnterSharedDebug, PDMCritSectRwLeaveShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwTryEnterShared.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwTryEnterShared(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifndef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterShared(pThis, VERR_SEM_BUSY, NULL, true /*fTryOnly*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterShared(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryOnly*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Try enter a critical section with shared (read) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uId Where we're entering the section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFile The source position - file.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param iLine The source position - line.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFunction The source position - function.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwTryEnterShared, PDMCritSectRwEnterShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwEnterSharedDebug, PDMCritSectRwLeaveShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwTryEnterSharedDebug.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwTryEnterSharedDebug(PPDMCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterShared(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryOnly*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Leave a critical section held with shared access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwEnterShared, PDMCritSectRwTryEnterShared,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwEnterSharedDebug, PDMCritSectRwTryEnterSharedDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwLeaveExcl, RTCritSectRwLeaveShared.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwLeaveShared(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate handle.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Check the direction and take action accordingly.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9 = RTLockValidatorRecSharedCheckAndRelease(pThis->s.Core.pValidatorRead, NIL_RTTHREAD);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(c > 0, VERR_NOT_OWNER);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c--;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ( c > 0
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync || (u64State & RTCSRW_CNT_RD_MASK) == 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Don't change the direction. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_CNT_RD_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= c << RTCSRW_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Reverse the direction and signal the reader threads. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_DIR_MASK);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc = SUPSemEventSignal(pThis->s.CTX_SUFF(pVM)->pSession, (SUPSEMEVENT)pThis->s.Core.hEvtWrite);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertRC(rc);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMNopPause();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(hNativeSelf == hNativeWriter, VERR_NOT_OWNER);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.cWriterReads > 0, VERR_NOT_OWNER);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc = RTLockValidatorRecExclUnwindMixed(pThis->s.Core.pValidatorWrite, &pThis->s.Core.pValidatorRead->Core);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicDecU32(&pThis->s.Core.cWriterReads);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VINF_SUCCESS;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncstatic int pdmCritSectRwEnterExcl(PPDMCRITSECTRW pThis, int rcBusy, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate input.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTTHREAD hThreadSelf = NIL_RTTHREAD;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (!fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync hThreadSelf = RTThreadSelfAutoAdopt();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9 = RTLockValidatorRecExclCheckOrder(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Check if we're already the owner and just recursing.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (hNativeSelf == hNativeWriter)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert((ASMAtomicReadU64(&pThis->s.Core.u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9 = RTLockValidatorRecExclRecursion(pThis->s.Core.pValidatorWrite, pSrcPos);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(pThis->s.Core.cWriteRecursions < UINT32_MAX / 2);
1e492a1641955148d5024f44aa35a2084bcc47d3vboxsync STAM_REL_COUNTER_INC(&pThis->s.CTX_MID_Z(Stat,EnterExcl));
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicIncU32(&pThis->s.Core.cWriteRecursions);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VINF_SUCCESS;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Get cracking.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ( (u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync || (u64State & (RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK)) != 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* It flows in the right direction, try follow it before it changes. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c++;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else if ((u64State & (RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK)) == 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Wrong direction, but we're alone here and can simply try switch the direction. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= (UINT64_C(1) << RTCSRW_CNT_WR_SHIFT) | (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else if (fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Wrong direction and we're not supposed to wait, just return. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_BUSY;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Add ourselves to the write count and break out to do the wait. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c++;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_DESTROYED;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMNopPause();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * If we're in write mode now try grab the ownership. Play fair if there
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * are threads already waiting.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync bool fDone = (u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync && ( ((u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT) == 1
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync || fTryOnly);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (fDone)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicCmpXchgHandle(&pThis->s.Core.hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (!fDone)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Wait for our turn.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (uint32_t iLoop = 0; ; iLoop++)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (!fTryOnly)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (hThreadSelf == NIL_RTTHREAD)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync hThreadSelf = RTThreadSelfAutoAdopt();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc = RTLockValidatorRecExclCheckBlocking(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, true,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_WRITE, false);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc = VINF_SUCCESS;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_SUCCESS(rc))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTTHREAD hThreadSelf = RTThreadSelf();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, false);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync do
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync rc = SUPSemEventWaitNoResume(pThis->s.CTX_SUFF(pVM)->pSession,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync (SUPSEMEVENT)pThis->s.Core.hEvtWrite,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RT_INDEFINITE_WAIT);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync while (rc == VERR_INTERRUPTED && pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_DESTROYED;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Decrement the counts and return the error. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64OldState = u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT; Assert(c > 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c--;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicCmpXchgHandle(&pThis->s.Core.hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (fDone)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertMsg(iLoop < 1000, ("%u\n", iLoop)); /* may loop a few times here... */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Got it!
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert((ASMAtomicReadU64(&pThis->s.Core.u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicWriteU32(&pThis->s.Core.cWriteRecursions, 1);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(pThis->s.Core.cWriterReads == 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLockValidatorRecExclSetOwner(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, true);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
1e492a1641955148d5024f44aa35a2084bcc47d3vboxsync STAM_REL_COUNTER_INC(&pThis->s.CTX_MID_Z(Stat,EnterExcl));
1e492a1641955148d5024f44aa35a2084bcc47d3vboxsync STAM_PROFILE_ADV_START(&pThis->s.StatWriteLocked, swl);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VINF_SUCCESS;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Try enter a critical section with exclusive (write) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @a rcBusy if in ring-0 or raw-mode context and it is busy.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param rcBusy The status code to return when we're in RC or R0 and the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * section is busy. Pass VINF_SUCCESS to acquired the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * critical section thru a ring-3 call if necessary.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwEnterExclDebug, PDMCritSectRwTryEnterExcl,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwTryEnterExclDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectEnterDebug, PDMCritSectEnter,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwEnterExcl.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwEnterExcl(PPDMCRITSECTRW pThis, int rcBusy)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifndef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterExcl(pThis, rcBusy, NULL, false /*fTryAgain*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterExcl(pThis, rcBusy, &SrcPos, false /*fTryAgain*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Try enter a critical section with exclusive (write) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @a rcBusy if in ring-0 or raw-mode context and it is busy.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param rcBusy The status code to return when we're in RC or R0 and the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * section is busy. Pass VINF_SUCCESS to acquired the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * critical section thru a ring-3 call if necessary.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uId Where we're entering the section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFile The source position - file.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param iLine The source position - line.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFunction The source position - function.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwEnterExcl, PDMCritSectRwTryEnterExcl,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwTryEnterExclDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectEnterDebug, PDMCritSectEnter,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwEnterExclDebug.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwEnterExclDebug(PPDMCRITSECTRW pThis, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterExcl(pThis, rcBusy, &SrcPos, false /*fTryAgain*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Try enter a critical section with exclusive (write) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwEnterExcl, PDMCritSectRwTryEnterExclDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwEnterExclDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectTryEnter, PDMCritSectTryEnterDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwTryEnterExcl.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwTryEnterExcl(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifndef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterExcl(pThis, VERR_SEM_BUSY, NULL, true /*fTryAgain*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterExcl(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryAgain*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Try enter a critical section with exclusive (write) access.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VINF_SUCCESS on success.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param uId Where we're entering the section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFile The source position - file.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param iLine The source position - line.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pszFunction The source position - function.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwTryEnterExcl, PDMCritSectRwEnterExcl,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectRwEnterExclDebug,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * PDMCritSectTryEnterDebug, PDMCritSectTryEnter,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwTryEnterExclDebug.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwTryEnterExclDebug(PPDMCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pdmCritSectRwEnterExcl(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryAgain*/);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Leave a critical section held exclusively.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns VBox status code.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval VERR_SEM_DESTROYED if the critical section is delete before or
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * during the operation.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwLeaveShared, RTCritSectRwLeaveExcl.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(int) PDMCritSectRwLeaveExcl(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate handle.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(hNativeSelf == hNativeWriter, VERR_NOT_OWNER);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Unwind a recursion.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (pThis->s.Core.cWriteRecursions == 1)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.cWriterReads == 0, VERR_WRONG_ORDER); /* (must release all read recursions before the final write.) */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9 = RTLockValidatorRecExclReleaseOwner(pThis->s.Core.pValidatorWrite, true);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Update the state.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicWriteU32(&pThis->s.Core.cWriteRecursions, 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicWriteHandle(&pThis->s.Core.hNativeWriter, NIL_RTNATIVETHREAD);
1e492a1641955148d5024f44aa35a2084bcc47d3vboxsync STAM_PROFILE_ADV_STOP(&pThis->s.StatWriteLocked, swl);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync for (;;)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64OldState = u64State;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(c > 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync c--;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ( c > 0
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync || (u64State & RTCSRW_CNT_RD_MASK) == 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Don't change the direction, wait up the next writer if any. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (c > 0)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc = SUPSemEventSignal(pThis->s.CTX_SUFF(pVM)->pSession, (SUPSEMEVENT)pThis->s.Core.hEvtWrite);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertRC(rc);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /* Reverse the direction and signal the reader threads. */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State &= ~(RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync u64State |= RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(!pThis->s.Core.fNeedReset);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicWriteBool(&pThis->s.Core.fNeedReset, true);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc = SUPSemEventMultiSignal(pThis->s.CTX_SUFF(pVM)->pSession, (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertRC(rc);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync break;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMNopPause();
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VERR_SEM_DESTROYED;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync Assert(pThis->s.Core.cWriteRecursions != 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#ifdef PDMCRITSECTRW_STRICT
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync int rc9 = RTLockValidatorRecExclUnwind(pThis->s.Core.pValidatorWrite);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (RT_FAILURE(rc9))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return rc9;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicDecU32(&pThis->s.Core.cWriteRecursions);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return VINF_SUCCESS;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Checks the caller is the exclusive (write) owner of the critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @c true if owner.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @c false if not owner.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwIsReadOwner, PDMCritSectIsOwner,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwIsWriteOwner.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(bool) PDMCritSectRwIsWriteOwner(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate handle.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, false);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Check ownership.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hNativeWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (hNativeWriter == NIL_RTNATIVETHREAD)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return false;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return hNativeWriter == pdmCritSectRwGetNativeSelf(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Checks if the caller is one of the read owners of the critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @note !CAUTION! This API doesn't work reliably if lock validation isn't
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * enabled. Meaning, the answer is not trustworhty unless
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RT_LOCK_STRICT or PDMCRITSECTRW_STRICT was defined at build time.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Also, make sure you do not use RTCRITSECTRW_FLAGS_NO_LOCK_VAL when
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * creating the semaphore. And finally, if you used a locking class,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * don't disable deadlock detection by setting cMsMinDeadlock to
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RT_INDEFINITE_WAIT.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * In short, only use this for assertions.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns @c true if reader, @c false if not.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param fWannaHear What you'd like to hear when lock validation is not
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * available. (For avoiding asserting all over the place.)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwIsWriteOwner, RTCritSectRwIsReadOwner.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(bool) PDMCritSectRwIsReadOwner(PPDMCRITSECTRW pThis, bool fWannaHear)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate handle.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, false);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Inspect the state.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync {
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * It's in write mode, so we can only be a reader if we're also the
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * current writer.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync RTNATIVETHREAD hWriter;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hWriter);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (hWriter == NIL_RTNATIVETHREAD)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return false;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return hWriter == pdmCritSectRwGetNativeSelf(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync }
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Read mode. If there are no current readers, then we cannot be a reader.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if (!(u64State & RTCSRW_CNT_RD_MASK))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return false;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#if defined(PDMCRITSECTRW_STRICT) && defined(IN_RING3)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Ask the lock validator.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Note! It doesn't know everything, let's deal with that if it becomes an issue...
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return RTLockValidatorRecSharedIsOwner(pThis->s.Core.pValidatorRead, NIL_RTTHREAD);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#else
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Ok, we don't know, just tell the caller what he want to hear.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return fWannaHear;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync#endif
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Gets the write recursion count.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns The write recursion count (0 if bad critsect).
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwGetWriterReadRecursion, PDMCritSectRwGetReadCount,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwGetWriteRecursion.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(uint32_t) PDMCritSectRwGetWriteRecursion(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate handle.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Return the requested data.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pThis->s.Core.cWriteRecursions;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Gets the read recursion count of the current writer.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns The read recursion count (0 if bad critsect).
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwGetWriteRecursion, PDMCritSectRwGetReadCount,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwGetWriterReadRecursion.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(uint32_t) PDMCritSectRwGetWriterReadRecursion(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate handle.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Return the requested data.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pThis->s.Core.cWriterReads;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Gets the current number of reads.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * This includes all read recursions, so it might be higher than the number of
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * read owners. It does not include reads done by the current writer.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @returns The read count (0 if bad critsect).
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectRwGetWriteRecursion, PDMCritSectRwGetWriterReadRecursion,
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * RTCritSectRwGetReadCount.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(uint32_t) PDMCritSectRwGetReadCount(PPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Validate input.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, 0);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync /*
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Return the requested data.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync if ((u64State & RTCSRW_DIR_MASK) != (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return 0;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync/**
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * Checks if the read/write critical section is initialized or not.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync *
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @c true if initialized.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @retval @c false if not initialized.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @param pThis Pointer to the read/write critical section.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync * @sa PDMCritSectIsInitialized, RTCritSectRwIsInitialized.
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync */
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsyncVMMDECL(bool) PDMCritSectRwIsInitialized(PCPDMCRITSECTRW pThis)
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync{
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync AssertPtr(pThis);
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync return pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC;
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync}
a0352d06ef77cf45a08eb08b4d65d570b7b294cbvboxsync