PDMAllCritSect.cpp revision 4b0369e0c9bcae37f2801e0f7b92509bbbaf4bec
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/* $Id$ */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/** @file
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * PDM - Critical Sections, All Contexts.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * available from http://www.virtualbox.org. This file is free software;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * you can redistribute it and/or modify it under the terms of the GNU
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * General Public License (GPL) as published by the Free Software
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * additional information or have any questions.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync/*******************************************************************************
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync* Header Files *
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync*******************************************************************************/
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#define LOG_GROUP LOG_GROUP_PDM//_CRITSECT
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include "PDMInternal.h"
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/pdmcritsect.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/mm.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/vmm.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/vm.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/err.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/hwaccm.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <VBox/log.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <iprt/asm.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#include <iprt/assert.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#ifdef IN_RING3
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync# include <iprt/lockvalidator.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync# include <iprt/semaphore.h>
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#endif
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/*******************************************************************************
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync* Defined Constants And Macros *
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync*******************************************************************************/
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/** The number loops to spin for in ring-3. */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#define PDMCRITSECT_SPIN_COUNT_R3 20
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/** The number loops to spin for in ring-0. */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#define PDMCRITSECT_SPIN_COUNT_R0 256
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync/** The number loops to spin for in the raw-mode context. */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#define PDMCRITSECT_SPIN_COUNT_RC 256
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/* Undefine the automatic VBOX_STRICT API mappings. */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#undef PDMCritSectEnter
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#undef PDMCritSectTryEnter
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/**
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * Gets the ring-3 native thread handle of the calling thread.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync *
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @returns native thread handle (ring-3).
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @param pCritSect The critical section. This is used in R0 and RC.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsyncDECL_FORCE_INLINE(RTNATIVETHREAD) pdmCritSectGetNativeSelf(PCPDMCRITSECT pCritSect)
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync{
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#ifdef IN_RING3
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync NOREF(pCritSect);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#else
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync AssertMsgReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, ("%RX32\n", pCritSect->s.Core.u32Magic),
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync VERR_SEM_DESTROYED);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync PVM pVM = pCritSect->s.CTX_SUFF(pVM); AssertPtr(pVM);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync PVMCPU pVCpu = VMMGetCpu(pVM); AssertPtr(pVCpu);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync RTNATIVETHREAD hNativeSelf = pVCpu->hNativeThread; Assert(hNativeSelf != NIL_RTNATIVETHREAD);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#endif
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync return hNativeSelf;
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync}
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/**
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * Tail code called when we've wont the battle for the lock.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync *
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @returns VINF_SUCCESS.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync *
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @param pCritSect The critical section.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @param hNativeSelf The native handle of this thread.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsyncDECL_FORCE_INLINE(int) pdmCritSectEnterFirst(PPDMCRITSECT pCritSect, RTNATIVETHREAD hNativeSelf, PCRTLOCKVALIDATORSRCPOS pSrcPos)
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync{
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync AssertMsg(pCritSect->s.Core.NativeThreadOwner == NIL_RTNATIVETHREAD, ("NativeThreadOwner=%p\n", pCritSect->s.Core.NativeThreadOwner));
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync Assert(!(pCritSect->s.Core.fFlags & PDMCRITSECT_FLAGS_PENDING_UNLOCK));
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync ASMAtomicWriteS32(&pCritSect->s.Core.cNestings, 1);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync ASMAtomicWriteHandle(&pCritSect->s.Core.NativeThreadOwner, hNativeSelf);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync# ifdef PDMCRITSECT_STRICT
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync RTLockValidatorSetOwner(pCritSect->s.Core.pValidatorRec, NIL_RTTHREAD, pSrcPos);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync# endif
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync STAM_PROFILE_ADV_START(&pCritSect->s.StatLocked, l);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync return VINF_SUCCESS;
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync}
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync#ifdef IN_RING3
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync/**
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * Deals with the contended case in ring-3.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync *
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @returns VINF_SUCCESS or VERR_SEM_DESTROYED.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @param pCritSect The critsect.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * @param hNativeSelf The native thread handle.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync */
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsyncstatic int pdmR3CritSectEnterContended(PPDMCRITSECT pCritSect, RTNATIVETHREAD hNativeSelf, PCRTLOCKVALIDATORSRCPOS pSrcPos)
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync{
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync /*
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync * Start waiting.
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync */
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync if (ASMAtomicIncS32(&pCritSect->s.Core.cLockers) == 0)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_COUNTER_INC(&pCritSect->s.StatContentionR3);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * The wait loop.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PSUPDRVSESSION pSession = pCritSect->s.CTX_SUFF(pVM)->pSession;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync SUPSEMEVENT hEvent = (SUPSEMEVENT)pCritSect->s.Core.EventSem;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# ifdef PDMCRITSECT_STRICT
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int rc2 = RTLockValidatorCheckOrder(pCritSect->s.Core.pValidatorRec, hThreadSelf, pSrcPos);
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync if (RT_FAILURE(rc2))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return rc2;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTTHREAD hThreadSelf = RTThreadSelf();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync for (;;)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# ifdef PDMCRITSECT_STRICT
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int rc9 = RTLockValidatorCheckBlocking(pCritSect->s.Core.pValidatorRec, hThreadSelf, RTTHREADSTATE_CRITSECT,
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync !(pCritSect->s.Core.fFlags & RTCRITSECT_FLAGS_NO_NESTING), pSrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (RT_FAILURE(rc9))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return rc9;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_CRITSECT);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int rc = SUPSemEventWaitNoResume(pSession, hEvent, RT_INDEFINITE_WAIT);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_CRITSECT);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (RT_UNLIKELY(pCritSect->s.Core.u32Magic != RTCRITSECT_MAGIC))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return VERR_SEM_DESTROYED;
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync if (rc == VINF_SUCCESS)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertMsg(rc == VERR_INTERRUPTED, ("rc=%Rrc\n", rc));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* won't get here */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif /* IN_RING3 */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Common worker for the debug and normal APIs.
d331ca5667e19a46f1e967617184483bec985e86vboxsync *
d331ca5667e19a46f1e967617184483bec985e86vboxsync * @returns VINF_SUCCESS if entered successfully.
d331ca5667e19a46f1e967617184483bec985e86vboxsync * @returns rcBusy when encountering a busy critical section in GC/R0.
d331ca5667e19a46f1e967617184483bec985e86vboxsync * @returns VERR_SEM_DESTROYED if the critical section is dead.
d331ca5667e19a46f1e967617184483bec985e86vboxsync *
d331ca5667e19a46f1e967617184483bec985e86vboxsync * @param pCritSect The PDM critical section to enter.
d331ca5667e19a46f1e967617184483bec985e86vboxsync * @param rcBusy The status code to return when we're in GC or R0
d331ca5667e19a46f1e967617184483bec985e86vboxsync * and the section is busy.
d331ca5667e19a46f1e967617184483bec985e86vboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncDECL_FORCE_INLINE(int) pdmCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy, PCRTLOCKVALIDATORSRCPOS pSrcPos)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync Assert(pCritSect->s.Core.cNestings < 8); /* useful to catch incorrect locking */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync /*
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync * If the critical section has already been destroyed, then inform the caller.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync AssertMsgReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC,
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync ("%p %RX32\n", pCritSect, pCritSect->s.Core.u32Magic),
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync VERR_SEM_DESTROYED);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * See if we're lucky.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTNATIVETHREAD hNativeSelf = pdmCritSectGetNativeSelf(pCritSect);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* Not owned ... */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* ... or nested. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (pCritSect->s.Core.NativeThreadOwner == hNativeSelf)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync ASMAtomicIncS32(&pCritSect->s.Core.cLockers);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicIncS32(&pCritSect->s.Core.cNestings);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync ASMAtomicAndU32(&pCritSect->s.Core.fFlags, ~PDMCRITSECT_FLAGS_PENDING_UNLOCK);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return VINF_SUCCESS;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Spin for a bit without incrementing the counter.
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /** @todo Move this to cfgm variables since it doesn't make sense to spin on UNI
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * cpu systems. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int32_t cSpinsLeft = CTX_SUFF(PDMCRITSECT_SPIN_COUNT_);
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync while (cSpinsLeft-- > 0)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMNopPause();
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync /** @todo Should use monitor/mwait on e.g. &cLockers here, possibly with a
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync cli'ed pendingpreemption check up front using sti w/ instruction fusing
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync for avoiding races. Hmm ... This is assuming the other party is actually
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync executing code on another CPU ... which we could keep track of if we
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync wanted. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef IN_RING3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Take the slow path.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmR3CritSectEnterContended(pCritSect, hNativeSelf, pSrcPos);
66a94fee6b0acc21c078369f49d97020cc03ab11vboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Return busy.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_REL_COUNTER_INC(&pCritSect->s.StatContentionRZLock);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync LogFlow(("PDMCritSectEnter: locked => R3 (%Rrc)\n", rcBusy));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return rcBusy;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Enters a PDM critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns VINF_SUCCESS if entered successfully.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns rcBusy when encountering a busy critical section in GC/R0.
d1cbcedef8f8eb139111351e183add8c0b7d3645vboxsync * @returns VERR_SEM_DESTROYED if the critical section is dead.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The PDM critical section to enter.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param rcBusy The status code to return when we're in GC or R0
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * and the section is busy.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(int) PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifndef PDMCRITSECT_STRICT
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnter(pCritSect, rcBusy, NULL);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTLOCKVALIDATORSRCPOS SrcPos = RTLOCKVALIDATORSRCPOS_INIT_NORMAL_API();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnter(pCritSect, rcBusy, &SrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Enters a PDM critical section, with location information for debugging.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns VINF_SUCCESS if entered successfully.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns rcBusy when encountering a busy critical section in GC/R0.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns VERR_SEM_DESTROYED if the critical section is dead.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The PDM critical section to enter.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param rcBusy The status code to return when we're in GC or R0
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * and the section is busy.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param uId Some kind of locking location ID. Typically a
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * return address up the stack. Optional (0).
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pszFile The file where the lock is being acquired from.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Optional.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param iLine The line number in that file. Optional (0).
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pszFunction The functionn where the lock is being acquired
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * from. Optional.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(int) PDMCritSectEnterDebug(PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef PDMCRITSECT_STRICT
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTLOCKVALIDATORSRCPOS SrcPos = RTLOCKVALIDATORSRCPOS_INIT_DEBUG_API();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnter(pCritSect, rcBusy, &SrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnter(pCritSect, rcBusy, NULL);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Common worker for the debug and normal APIs.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VINF_SUCCESS on success.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncstatic int pdmCritSectTryEnter(PPDMCRITSECT pCritSect, PCRTLOCKVALIDATORSRCPOS pSrcPos)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * If the critical section has already been destroyed, then inform the caller.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertMsgReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC,
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ("%p %RX32\n", pCritSect, pCritSect->s.Core.u32Magic),
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync VERR_SEM_DESTROYED);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * See if we're lucky.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTNATIVETHREAD hNativeSelf = pdmCritSectGetNativeSelf(pCritSect);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* Not owned ... */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
66a94fee6b0acc21c078369f49d97020cc03ab11vboxsync /* ... or nested. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (pCritSect->s.Core.NativeThreadOwner == hNativeSelf)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicIncS32(&pCritSect->s.Core.cLockers);
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync ASMAtomicIncS32(&pCritSect->s.Core.cNestings);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicAndU32(&pCritSect->s.Core.fFlags, ~PDMCRITSECT_FLAGS_PENDING_UNLOCK);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return VINF_SUCCESS;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* no spinning */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Return busy.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef IN_RING3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_REL_COUNTER_INC(&pCritSect->s.StatContentionR3);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_REL_COUNTER_INC(&pCritSect->s.StatContentionRZLock);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync LogFlow(("PDMCritSectTryEnter: locked\n"));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return VERR_SEM_BUSY;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Try enter a critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VINF_SUCCESS on success.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(int) PDMCritSectTryEnter(PPDMCRITSECT pCritSect)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifndef PDMCRITSECT_STRICT
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectTryEnter(pCritSect, NULL);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTLOCKVALIDATORSRCPOS SrcPos = RTLOCKVALIDATORSRCPOS_INIT_NORMAL_API();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectTryEnter(pCritSect, &SrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Try enter a critical section, with location information for debugging.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VINF_SUCCESS on success.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_BUSY if the critsect was owned.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param uId Some kind of locking location ID. Typically a
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * return address up the stack. Optional (0).
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pszFile The file where the lock is being acquired from.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Optional.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param iLine The line number in that file. Optional (0).
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync * @param pszFunction The functionn where the lock is being acquired
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * from. Optional.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(int) PDMCritSectTryEnterDebug(PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef PDMCRITSECT_STRICT
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTLOCKVALIDATORSRCPOS SrcPos = RTLOCKVALIDATORSRCPOS_INIT_DEBUG_API();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectTryEnter(pCritSect, &SrcPos);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pdmCritSectTryEnter(pCritSect, NULL);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef IN_RING3
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync/**
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync * Enters a PDM critical section.
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns VINF_SUCCESS if entered successfully.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns rcBusy when encountering a busy critical section in GC/R0.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns VERR_SEM_DESTROYED if the critical section is dead.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The PDM critical section to enter.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param fCallRing3 Whether this is a VMMRZCallRing3()request.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMR3DECL(int) PDMR3CritSectEnterEx(PPDMCRITSECT pCritSect, bool fCallRing3)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int rc = PDMCritSectEnter(pCritSect, VERR_INTERNAL_ERROR);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if ( rc == VINF_SUCCESS
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync && fCallRing3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync && pCritSect->s.Core.pValidatorRec
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync && pCritSect->s.Core.pValidatorRec->hThread != NIL_RTTHREAD)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTLockValidatorUnsetOwner(pCritSect->s.Core.pValidatorRec);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return rc;
66a94fee6b0acc21c078369f49d97020cc03ab11vboxsync}
66a94fee6b0acc21c078369f49d97020cc03ab11vboxsync#endif /* IN_RING3 */
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Leaves a critical section entered with PDMCritSectEnter().
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync * @param pCritSect The PDM critical section to leave.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(void) PDMCritSectLeave(PPDMCRITSECT pCritSect)
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync{
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync AssertMsg(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, ("%p %RX32\n", pCritSect, pCritSect->s.Core.u32Magic));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync Assert(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync Assert(pCritSect->s.Core.NativeThreadOwner == pdmCritSectGetNativeSelf(pCritSect));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync Assert(pCritSect->s.Core.cNestings >= 1);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync /*
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync * Nested leave.
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync */
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync if (pCritSect->s.Core.cNestings > 1)
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync {
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync ASMAtomicDecS32(&pCritSect->s.Core.cNestings);
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync ASMAtomicDecS32(&pCritSect->s.Core.cLockers);
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync return;
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync }
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync#ifdef IN_RING0
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# if 0 /** @todo Make SUPSemEventSignal interrupt safe (handle table++) and enable this for: defined(RT_OS_LINUX) || defined(RT_OS_OS2) */
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync if (1) /* SUPSemEventSignal is safe */
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# else
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync if (ASMIntAreEnabled())
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# endif
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync#endif
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync#if defined(IN_RING3) || defined(IN_RING0)
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync {
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync /*
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync * Leave for real.
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync */
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync /* update members. */
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# ifdef IN_RING3
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync RTSEMEVENT hEventToSignal = pCritSect->s.EventToSignal;
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync pCritSect->s.EventToSignal = NIL_RTSEMEVENT;
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# if defined(PDMCRITSECT_STRICT)
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync if (pCritSect->s.Core.pValidatorRec->hThread != NIL_RTTHREAD)
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync RTLockValidatorUnsetOwner(pCritSect->s.Core.pValidatorRec);
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# endif
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync Assert(!pCritSect->s.Core.pValidatorRec || pCritSect->s.Core.pValidatorRec->hThread == NIL_RTTHREAD);
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync# endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicAndU32(&pCritSect->s.Core.fFlags, ~PDMCRITSECT_FLAGS_PENDING_UNLOCK);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicWriteHandle(&pCritSect->s.Core.NativeThreadOwner, NIL_RTNATIVETHREAD);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicDecS32(&pCritSect->s.Core.cNestings);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* stop and decrement lockers. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_PROFILE_ADV_STOP(&pCritSect->s.StatLocked, l);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMCompilerBarrier();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (ASMAtomicDecS32(&pCritSect->s.Core.cLockers) >= 0)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* Someone is waiting, wake up one of them. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync SUPSEMEVENT hEvent = (SUPSEMEVENT)pCritSect->s.Core.EventSem;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PSUPDRVSESSION pSession = pCritSect->s.CTX_SUFF(pVM)->pSession;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int rc = SUPSemEventSignal(pSession, hEvent);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertRC(rc);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# ifdef IN_RING3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* Signal exit event. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (hEventToSignal != NIL_RTSEMEVENT)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync LogBird(("Signalling %#x\n", hEventToSignal));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync int rc = RTSemEventSignal(hEventToSignal);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertRC(rc);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# if defined(DEBUG_bird) && defined(IN_RING0)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync VMMTrashVolatileXMMRegs();
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif /* IN_RING3 || IN_RING0 */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef IN_RING0
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#if defined(IN_RING0) || defined(IN_RC)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Try leave it.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (pCritSect->s.Core.cLockers == 0)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicWriteS32(&pCritSect->s.Core.cNestings, 0);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync RTNATIVETHREAD hNativeThread = pCritSect->s.Core.NativeThreadOwner;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicAndU32(&pCritSect->s.Core.fFlags, ~PDMCRITSECT_FLAGS_PENDING_UNLOCK);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_PROFILE_ADV_STOP(&pCritSect->s.StatLocked, l);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicWriteHandle(&pCritSect->s.Core.NativeThreadOwner, NIL_RTNATIVETHREAD);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, -1, 0))
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /* darn, someone raced in on us. */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicWriteHandle(&pCritSect->s.Core.NativeThreadOwner, hNativeThread);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_PROFILE_ADV_START(&pCritSect->s.StatLocked, l);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicWriteS32(&pCritSect->s.Core.cNestings, 1);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync ASMAtomicOrU32(&pCritSect->s.Core.fFlags, PDMCRITSECT_FLAGS_PENDING_UNLOCK);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync /*
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Queue the request.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PVM pVM = pCritSect->s.CTX_SUFF(pVM); AssertPtr(pVM);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PVMCPU pVCpu = VMMGetCpu(pVM); AssertPtr(pVCpu);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync uint32_t i = pVCpu->pdm.s.cQueuedCritSectLeaves++;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync LogFlow(("PDMCritSectLeave: [%d]=%p => R3\n", i, pCritSect));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertFatal(i < RT_ELEMENTS(pVCpu->pdm.s.apQueuedCritSectsLeaves));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync pVCpu->pdm.s.apQueuedCritSectsLeaves[i] = MMHyperCCToR3(pVM, pCritSect);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync VMCPU_FF_SET(pVCpu, VMCPU_FF_PDM_CRITSECT);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_REL_COUNTER_INC(&pVM->pdm.s.StatQueuedCritSectLeaves);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync STAM_REL_COUNTER_INC(&pCritSect->s.StatContentionRZUnlock);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif /* IN_RING0 || IN_RC */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
0e8453fd4bba7dd5e9ffe786904f7114393fb69cvboxsync#if defined(IN_RING3) || defined(IN_RING0)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Process the critical sections queued for ring-3 'leave'.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pVCpu The VMCPU handle.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(void) PDMCritSectFF(PVMCPU pVCpu)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync Assert(pVCpu->pdm.s.cQueuedCritSectLeaves > 0);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync const RTUINT c = pVCpu->pdm.s.cQueuedCritSectLeaves;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync for (RTUINT i = 0; i < c; i++)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync {
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# ifdef IN_RING3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PPDMCRITSECT pCritSect = pVCpu->pdm.s.apQueuedCritSectsLeaves[i];
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# else
0e8453fd4bba7dd5e9ffe786904f7114393fb69cvboxsync PPDMCRITSECT pCritSect = (PPDMCRITSECT)MMHyperR3ToCC(pVCpu->CTX_SUFF(pVM), pVCpu->pdm.s.apQueuedCritSectsLeaves[i]);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync# endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PDMCritSectLeave(pCritSect);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync LogFlow(("PDMR3CritSectFF: %p\n", pCritSect));
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync }
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync pVCpu->pdm.s.cQueuedCritSectLeaves = 0;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PDM_CRITSECT);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif /* IN_RING3 || IN_RING0 */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Checks the caller is the owner of the critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns true if owner.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns false if not owner.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(bool) PDMCritSectIsOwner(PCPDMCRITSECT pCritSect)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef IN_RING3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return RTCritSectIsOwner(&pCritSect->s.Core);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PVM pVM = pCritSect->s.CTX_SUFF(pVM); AssertPtr(pVM);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PVMCPU pVCpu = VMMGetCpu(pVM); AssertPtr(pVCpu);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync if (pCritSect->s.Core.NativeThreadOwner != pVCpu->hNativeThread)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return false;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return (pCritSect->s.Core.fFlags & PDMCRITSECT_FLAGS_PENDING_UNLOCK) == 0;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Checks the specified VCPU is the owner of the critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns true if owner.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns false if not owner.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param idCpu VCPU id
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(bool) PDMCritSectIsOwnerEx(PCPDMCRITSECT pCritSect, VMCPUID idCpu)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#ifdef IN_RING3
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync NOREF(idCpu);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return RTCritSectIsOwner(&pCritSect->s.Core);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#else
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync PVM pVM = pCritSect->s.CTX_SUFF(pVM);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertPtr(pVM);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync Assert(idCpu < pVM->cCpus);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return pCritSect->s.Core.NativeThreadOwner == pVM->aCpus[idCpu].hNativeThread
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync && (pCritSect->s.Core.fFlags & PDMCRITSECT_FLAGS_PENDING_UNLOCK) == 0;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync#endif
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Checks if somebody currently owns the critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns true if locked.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns false if not locked.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @remarks This doesn't prove that no deadlocks will occur later on; it's
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * just a debugging tool
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(bool) PDMCritSectIsOwned(PCPDMCRITSECT pCritSect)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync return pCritSect->s.Core.NativeThreadOwner != NIL_RTNATIVETHREAD
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync && (pCritSect->s.Core.fFlags & PDMCRITSECT_FLAGS_PENDING_UNLOCK) == 0;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Checks if anyone is waiting on the critical section we own.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns true if someone is waitings.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns false if no one is waiting.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(bool) PDMCritSectHasWaiters(PCPDMCRITSECT pCritSect)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync AssertReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, false);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync Assert(pCritSect->s.Core.NativeThreadOwner == pdmCritSectGetNativeSelf(pCritSect));
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync return pCritSect->s.Core.cLockers >= pCritSect->s.Core.cNestings;
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
fc080a2caa666d6cdc9f978d31b49587fdc91125vboxsync
fc080a2caa666d6cdc9f978d31b49587fdc91125vboxsync
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Checks if a critical section is initialized or not.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync *
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns true if initialized.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @returns false if not initialized.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(bool) PDMCritSectIsInitialized(PCPDMCRITSECT pCritSect)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return RTCritSectIsInitialized(&pCritSect->s.Core);
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync/**
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync * Gets the recursion depth.
fc080a2caa666d6cdc9f978d31b49587fdc91125vboxsync *
fc080a2caa666d6cdc9f978d31b49587fdc91125vboxsync * @returns The recursion depth.
fc080a2caa666d6cdc9f978d31b49587fdc91125vboxsync * @param pCritSect The critical section.
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync */
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsyncVMMDECL(uint32_t) PDMCritSectGetRecursion(PCPDMCRITSECT pCritSect)
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync{
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync return RTCritSectGetRecursion(&pCritSect->s.Core);
ddd5bf03356cc0515b0f42ed9048a6364e7eb1e2vboxsync}
96a93b5e6bd7da64f6be955c9fd7569b80c8ae2evboxsync