645c172620d19e7aceca8b5ba9a904619681099dvboxsync/* $Id$ */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync/** @file
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * IPRT - Read/Write Critical Section, Generic.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync/*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Copyright (C) 2009-2013 Oracle Corporation
645c172620d19e7aceca8b5ba9a904619681099dvboxsync *
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * available from http://www.virtualbox.org. This file is free software;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * General Public License (GPL) as published by the Free Software
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync *
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * The contents of this file may alternatively be used under the terms
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * of the Common Development and Distribution License Version 1.0
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * CDDL are applicable instead of those of the GPL.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync *
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * You may elect to license modified versions of this file under the
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * terms and conditions of either the GPL or the CDDL or both.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync/*******************************************************************************
645c172620d19e7aceca8b5ba9a904619681099dvboxsync* Header Files *
645c172620d19e7aceca8b5ba9a904619681099dvboxsync*******************************************************************************/
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#define RTCRITSECTRW_WITHOUT_REMAPPING
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#define RTASSERT_QUIET
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/critsect.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include "internal/iprt.h"
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/asm.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/assert.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/err.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/lockvalidator.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/mem.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/semaphore.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include <iprt/thread.h>
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include "internal/magics.h"
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#include "internal/strict.h"
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return RTCritSectRwInitEx(pThis, 0, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectRw");
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwInit);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags,
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(!(fFlags & ~( RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK
645c172620d19e7aceca8b5ba9a904619681099dvboxsync | RTCRITSECT_FLAGS_NOP )),
645c172620d19e7aceca8b5ba9a904619681099dvboxsync VERR_INVALID_PARAMETER);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Initialize the structure, allocate the lock validator stuff and sems.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->u32Magic = RTCRITSECTRW_MAGIC_DEAD;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->fNeedReset = false;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->u64State = 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->hNativeWriter = NIL_RTNATIVETHREAD;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->cWriterReads = 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->cWriteRecursions = 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->hEvtWrite = NIL_RTSEMEVENT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->hEvtRead = NIL_RTSEMEVENTMULTI;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->pValidatorWrite = NULL;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->pValidatorRead = NULL;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#if HC_ARCH_BITS == 32
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->HCPtrPadding = NIL_RTHCPTR;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
9da3a001da2e31abb393c3f0e4ac81cc647b94f0vboxsync bool const fLVEnabled = !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (!pszNameFmt)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync static uint32_t volatile s_iAnon = 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint32_t i = ASMAtomicIncU32(&s_iAnon) - 1;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTLockValidatorRecExclCreate(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
645c172620d19e7aceca8b5ba9a904619681099dvboxsync fLVEnabled, "RTCritSectRw-%u", i);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTLockValidatorRecSharedCreate(&pThis->pValidatorRead, hClass, uSubClass, pThis,
645c172620d19e7aceca8b5ba9a904619681099dvboxsync false /*fSignaller*/, fLVEnabled, "RTCritSectRw-%u", i);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync va_list va;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync va_start(va, pszNameFmt);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTLockValidatorRecExclCreateV(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
645c172620d19e7aceca8b5ba9a904619681099dvboxsync fLVEnabled, pszNameFmt, va);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync va_end(va);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync va_start(va, pszNameFmt);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedCreateV(&pThis->pValidatorRead, hClass, uSubClass, pThis,
645c172620d19e7aceca8b5ba9a904619681099dvboxsync false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync va_end(va);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTLockValidatorRecMakeSiblings(&pThis->pValidatorWrite->Core, &pThis->pValidatorRead->Core);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTSemEventMultiCreate(&pThis->hEvtRead);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTSemEventCreate(&pThis->hEvtWrite);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->u32Magic = RTCRITSECTRW_MAGIC;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTSemEventMultiDestroy(pThis->hEvtRead);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedDestroy(&pThis->pValidatorRead);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecExclDestroy(&pThis->pValidatorWrite);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwInitEx);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(!(pThis->fFlags & RTCRITSECT_FLAGS_NOP), RTLOCKVAL_SUB_CLASS_INVALID);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedSetSubClass(pThis->pValidatorRead, uSubClass);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return RTLockValidatorRecExclSetSubClass(pThis->pValidatorWrite, uSubClass);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync NOREF(uSubClass);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return RTLOCKVAL_SUB_CLASS_INVALID;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwSetSubClass);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncstatic int rtCritSectRwEnterShared(PRTCRITSECTRW pThis, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate input.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (!fTryOnly)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (hNativeWriter != NIL_RTTHREAD && hNativeWriter == RTThreadNativeSelf())
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc9 = RTLockValidatorRecExclCheckOrder(pThis->pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc9 = RTLockValidatorRecSharedCheckOrder(pThis->pValidatorRead, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Get cracking...
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* It flows in the right direction, try follow it before it changes. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c++;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_CNT_RD_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= c << RTCSRW_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedAddOwner(pThis->pValidatorRead, hThreadSelf, pSrcPos);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else if ((u64State & (RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK)) == 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Wrong direction, but we're alone here and can simply try switch the direction. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= (UINT64_C(1) << RTCSRW_CNT_RD_SHIFT) | (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(!pThis->fNeedReset);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedAddOwner(pThis->pValidatorRead, hThreadSelf, pSrcPos);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Is the writer perhaps doing a read recursion? */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (hNativeSelf == hNativeWriter)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9 = RTLockValidatorRecExclRecursionMixed(pThis->pValidatorWrite, &pThis->pValidatorRead->Core, pSrcPos);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->cWriterReads < UINT32_MAX / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicIncU32(&pThis->cWriterReads);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS; /* don't break! */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* If we're only trying, return already. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (fTryOnly)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_BUSY;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Add ourselves to the queue and wait for the direction to change. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c++;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync cWait++;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(cWait <= c);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(cWait < RTCSRW_CNT_MASK / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (uint32_t iLoop = 0; ; iLoop++)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTLockValidatorRecSharedCheckBlocking(pThis->pValidatorRead, hThreadSelf, pSrcPos, true,
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_READ, false);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTTHREAD hThreadSelf = RTThreadSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_READ, false);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTSemEventMultiWait(pThis->hEvtRead, RT_INDEFINITE_WAIT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_DESTROYED;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Decrement the counts and return the error. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64OldState = u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT; Assert(c > 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c--;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT; Assert(cWait > 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync cWait--;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->fNeedReset);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertMsg(iLoop < 1, ("%u\n", iLoop));
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Decrement the wait count and maybe reset the semaphore (if we're last). */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync cWait = (u64State & RTCSRW_WAIT_CNT_RD_MASK) >> RTCSRW_WAIT_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(cWait > 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync cWait--;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_WAIT_CNT_RD_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= cWait << RTCSRW_WAIT_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (cWait == 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicXchgBool(&pThis->fNeedReset, false))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc = RTSemEventMultiReset(pThis->hEvtRead);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertRCReturn(rc, rc);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedAddOwner(pThis->pValidatorRead, hThreadSelf, pSrcPos);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_DESTROYED;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMNopPause();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* got it! */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert((ASMAtomicReadU64(&pThis->u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT));
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifndef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterShared(pThis, NULL, false /*fTryOnly*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterShared(pThis, &SrcPos, false /*fTryOnly*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwEnterShared);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterShared(pThis, &SrcPos, false /*fTryOnly*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwEnterSharedDebug);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifndef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterShared(pThis, NULL, true /*fTryOnly*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterShared(pThis, &SrcPos, true /*fTryOnly*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwEnterShared);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterShared(pThis, &SrcPos, true /*fTryOnly*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwEnterSharedDebug);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate handle.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Check the direction and take action accordingly.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9 = RTLockValidatorRecSharedCheckAndRelease(pThis->pValidatorRead, NIL_RTTHREAD);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(c > 0, VERR_NOT_OWNER);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c--;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ( c > 0
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync || (u64State & RTCSRW_CNT_WR_MASK) == 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Don't change the direction. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_CNT_RD_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= c << RTCSRW_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Reverse the direction and signal the reader threads. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_DIR_MASK);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc = RTSemEventSignal(pThis->hEvtWrite);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertRC(rc);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMNopPause();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(hNativeSelf == hNativeWriter, VERR_NOT_OWNER);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->cWriterReads > 0, VERR_NOT_OWNER);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc = RTLockValidatorRecExclUnwindMixed(pThis->pValidatorWrite, &pThis->pValidatorRead->Core);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicDecU32(&pThis->cWriterReads);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwLeaveShared);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncstatic int rtCritSectRwEnterExcl(PRTCRITSECTRW pThis, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate input.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTTHREAD hThreadSelf = NIL_RTTHREAD;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (!fTryOnly)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync hThreadSelf = RTThreadSelfAutoAdopt();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9 = RTLockValidatorRecExclCheckOrder(pThis->pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Check if we're already the owner and just recursing.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (hNativeSelf == hNativeWriter)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert((ASMAtomicReadU64(&pThis->u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9 = RTLockValidatorRecExclRecursion(pThis->pValidatorWrite, pSrcPos);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->cWriteRecursions < UINT32_MAX / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicIncU32(&pThis->cWriteRecursions);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Get cracking.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ( (u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync || (u64State & (RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK)) != 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* It flows in the right direction, try follow it before it changes. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c++;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else if ((u64State & (RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK)) == 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Wrong direction, but we're alone here and can simply try switch the direction. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= (UINT64_C(1) << RTCSRW_CNT_WR_SHIFT) | (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else if (fTryOnly)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Wrong direction and we're not supposed to wait, just return. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_BUSY;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Add ourselves to the write count and break out to do the wait. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c++;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(c < RTCSRW_CNT_MASK / 2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_DESTROYED;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMNopPause();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * If we're in write mode now try grab the ownership. Play fair if there
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * are threads already waiting.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync bool fDone = (u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync && ( ((u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT) == 1
645c172620d19e7aceca8b5ba9a904619681099dvboxsync || fTryOnly);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (fDone)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicCmpXchgHandle(&pThis->hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (!fDone)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync /*
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync * If only trying, undo the above writer incrementation and return.
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync */
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync if (fTryOnly)
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync {
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync for (;;)
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync {
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync u64OldState = u64State = ASMAtomicReadU64(&pThis->u64State);
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT; Assert(c > 0);
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync c--;
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync break;
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync }
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync return VERR_SEM_BUSY;
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync }
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Wait for our turn.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (uint32_t iLoop = 0; ; iLoop++)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync if (hThreadSelf == NIL_RTTHREAD)
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync hThreadSelf = RTThreadSelfAutoAdopt();
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync rc = RTLockValidatorRecExclCheckBlocking(pThis->pValidatorWrite, hThreadSelf, pSrcPos, true,
d0a2a9ce3384a88aeb052555867cb9aea43142b7vboxsync RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_WRITE, false);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_SUCCESS(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTTHREAD hThreadSelf = RTThreadSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, false);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync rc = RTSemEventWait(pThis->hEvtWrite, RT_INDEFINITE_WAIT);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_DESTROYED;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Decrement the counts and return the error. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64OldState = u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT; Assert(c > 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c--;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicCmpXchgHandle(&pThis->hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (fDone)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertMsg(iLoop < 1000, ("%u\n", iLoop)); /* may loop a few times here... */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Got it!
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert((ASMAtomicReadU64(&pThis->u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicWriteU32(&pThis->cWriteRecursions, 1);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->cWriterReads == 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecExclSetOwner(pThis->pValidatorWrite, hThreadSelf, pSrcPos, true);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifndef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterExcl(pThis, NULL, false /*fTryAgain*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterExcl(pThis, &SrcPos, false /*fTryAgain*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwEnterExcl);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterExcl(pThis, &SrcPos, false /*fTryAgain*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwEnterExclDebug);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifndef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterExcl(pThis, NULL, true /*fTryAgain*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterExcl(pThis, &SrcPos, true /*fTryAgain*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwTryEnterExcl);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rtCritSectRwEnterExcl(pThis, &SrcPos, true /*fTryAgain*/);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwTryEnterExclDebug);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate handle.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(hNativeSelf == hNativeWriter, VERR_NOT_OWNER);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Unwind a recursion.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (pThis->cWriteRecursions == 1)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->cWriterReads == 0, VERR_WRONG_ORDER); /* (must release all read recursions before the final write.) */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9 = RTLockValidatorRecExclReleaseOwner(pThis->pValidatorWrite, true);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Update the state.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicWriteU32(&pThis->cWriteRecursions, 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicWriteHandle(&pThis->hNativeWriter, NIL_RTNATIVETHREAD);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync for (;;)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64OldState = u64State;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(c > 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync c--;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ( c > 0
645c172620d19e7aceca8b5ba9a904619681099dvboxsync || (u64State & RTCSRW_CNT_RD_MASK) == 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Don't change the direction, wait up the next writer if any. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~RTCSRW_CNT_WR_MASK;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= c << RTCSRW_CNT_WR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (c > 0)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc = RTSemEventSignal(pThis->hEvtWrite);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertRC(rc);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /* Reverse the direction and signal the reader threads. */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State &= ~(RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync u64State |= RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(!pThis->fNeedReset);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicWriteBool(&pThis->fNeedReset, true);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc = RTSemEventMultiSignal(pThis->hEvtRead);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertRC(rc);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync break;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMNopPause();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_SEM_DESTROYED;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->cWriteRecursions != 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc9 = RTLockValidatorRecExclUnwind(pThis->pValidatorWrite);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (RT_FAILURE(rc9))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return rc9;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicDecU32(&pThis->cWriteRecursions);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VINF_SUCCESS;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
a603c77e6761cc9b9e425b716b6fa8a683246babvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwLeaveExcl);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate handle.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, false);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Check ownership.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return hNativeWriter == hNativeSelf;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwIsWriteOwner);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate handle.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, false);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Inspect the state.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync {
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * It's in write mode, so we can only be a reader if we're also the
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * current writer.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTNATIVETHREAD hWriter;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hWriter);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return hWriter == hNativeSelf;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync }
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Read mode. If there are no current readers, then we cannot be a reader.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (!(u64State & RTCSRW_CNT_RD_MASK))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return false;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#ifdef RTCRITSECTRW_STRICT
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Ask the lock validator.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return RTLockValidatorRecSharedIsOwner(pThis->pValidatorRead, NIL_RTTHREAD);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#else
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Ok, we don't know, just tell the caller what he want to hear.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return fWannaHear;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync#endif
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwIsReadOwner);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate handle.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Return the requested data.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return pThis->cWriteRecursions;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwGetWriteRecursion);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate handle.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Return the requested data.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return pThis->cWriterReads;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
a603c77e6761cc9b9e425b716b6fa8a683246babvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwGetWriterReadRecursion);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
a603c77e6761cc9b9e425b716b6fa8a683246babvboxsyncRTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Validate input.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Return the requested data.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if ((u64State & RTCSRW_DIR_MASK) != (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
a603c77e6761cc9b9e425b716b6fa8a683246babvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwGetReadCount);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis)
645c172620d19e7aceca8b5ba9a904619681099dvboxsync{
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Assert free waiters and so on.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync AssertPtr(pThis);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->u32Magic == RTCRITSECTRW_MAGIC);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync //Assert(pThis->cNestings == 0);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync //Assert(pThis->cLockers == -1);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync Assert(pThis->hNativeWriter == NIL_RTNATIVETHREAD);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync /*
645c172620d19e7aceca8b5ba9a904619681099dvboxsync * Invalidate the structure and free the semaphores.
645c172620d19e7aceca8b5ba9a904619681099dvboxsync */
645c172620d19e7aceca8b5ba9a904619681099dvboxsync if (!ASMAtomicCmpXchgU32(&pThis->u32Magic, RTCRITSECTRW_MAGIC_DEAD, RTCRITSECTRW_MAGIC))
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return VERR_INVALID_PARAMETER;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->fFlags = 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->u64State = 0;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTSEMEVENT hEvtWrite = pThis->hEvtWrite;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->hEvtWrite = NIL_RTSEMEVENT;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTSEMEVENTMULTI hEvtRead = pThis->hEvtRead;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync pThis->hEvtRead = NIL_RTSEMEVENTMULTI;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc1 = RTSemEventDestroy(hEvtWrite); AssertRC(rc1);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync int rc2 = RTSemEventMultiDestroy(hEvtRead); AssertRC(rc2);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecSharedDestroy(&pThis->pValidatorRead);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync RTLockValidatorRecExclDestroy(&pThis->pValidatorWrite);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync
645c172620d19e7aceca8b5ba9a904619681099dvboxsync return RT_SUCCESS(rc1) ? rc2 : rc1;
645c172620d19e7aceca8b5ba9a904619681099dvboxsync}
645c172620d19e7aceca8b5ba9a904619681099dvboxsyncRT_EXPORT_SYMBOL(RTCritSectRwDelete);
645c172620d19e7aceca8b5ba9a904619681099dvboxsync