VirtualBox

Changeset 45152 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Mar 23, 2013 8:36:23 PM (12 years ago)
Author:
vboxsync
Message:

PDMCritSectRw: Early morphing stage - untested, ring-3 only.

Location:
trunk/src/VBox/VMM
Files:
1 added
11 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/Makefile.kmk

    r45091 r45152  
    181181        VMMAll/PDMAll.cpp \
    182182        VMMAll/PDMAllCritSect.cpp \
     183        VMMAll/PDMAllCritSectRw.cpp \
     184        VMMAll/PDMAllCritSectBoth.cpp \
    183185        VMMAll/PDMAllQueue.cpp \
    184186        VMMAll/PGMAll.cpp \
     
    412414        VMMAll/PDMAll.cpp \
    413415        VMMAll/PDMAllCritSect.cpp \
     416        VMMAll/PDMAllCritSectBoth.cpp \
    414417        VMMAll/PDMAllQueue.cpp \
    415418        VMMAll/PGMAll.cpp \
     
    519522        VMMAll/PDMAll.cpp \
    520523        VMMAll/PDMAllCritSect.cpp \
     524        VMMAll/PDMAllCritSectBoth.cpp \
    521525        VMMAll/PDMAllQueue.cpp \
    522526        VMMAll/PGMAll.cpp \
  • trunk/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp

    r44528 r45152  
    11/* $Id$ */
    22/** @file
    3  * PDM - Critical Sections, All Contexts.
     3 * PDM - Write-Only Critical Section, All Contexts.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    176176 * @returns VINF_SUCCESS if entered successfully.
    177177 * @returns rcBusy when encountering a busy critical section in GC/R0.
    178  * @returns VERR_SEM_DESTROYED if the critical section is dead.
     178 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     179 *          during the operation.
    179180 *
    180181 * @param   pCritSect           The PDM critical section to enter.
     
    312313 *
    313314 * @returns VINF_SUCCESS if entered successfully.
    314  * @returns rcBusy when encountering a busy critical section in GC/R0.
    315  * @returns VERR_SEM_DESTROYED if the critical section is dead.
     315 * @returns rcBusy when encountering a busy critical section in RC/R0.
     316 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     317 *          during the operation.
    316318 *
    317319 * @param   pCritSect           The PDM critical section to enter.
    318  * @param   rcBusy              The status code to return when we're in GC or R0
     320 * @param   rcBusy              The status code to return when we're in RC or R0
    319321 *                              and the section is busy.  Pass VINF_SUCCESS to
    320322 *                              acquired the critical section thru a ring-3
     
    336338 *
    337339 * @returns VINF_SUCCESS if entered successfully.
    338  * @returns rcBusy when encountering a busy critical section in GC/R0.
    339  * @returns VERR_SEM_DESTROYED if the critical section is dead.
     340 * @returns rcBusy when encountering a busy critical section in RC/R0.
     341 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     342 *          during the operation.
    340343 *
    341344 * @param   pCritSect           The PDM critical section to enter.
    342  * @param   rcBusy              The status code to return when we're in GC or R0
     345 * @param   rcBusy              The status code to return when we're in RC or R0
    343346 *                              and the section is busy.   Pass VINF_SUCCESS to
    344347 *                              acquired the critical section thru a ring-3
     
    370373 * @retval  VERR_SEM_BUSY if the critsect was owned.
    371374 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    372  * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     375 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     376 *          during the operation.
    373377 *
    374378 * @param   pCritSect   The critical section.
     
    425429 * @retval  VERR_SEM_BUSY if the critsect was owned.
    426430 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    427  * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     431 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     432 *          during the operation.
    428433 *
    429434 * @param   pCritSect   The critical section.
     
    446451 * @retval  VERR_SEM_BUSY if the critsect was owned.
    447452 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    448  * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     453 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     454 *          during the operation.
    449455 *
    450456 * @param   pCritSect           The critical section.
     
    475481 * @returns VINF_SUCCESS if entered successfully.
    476482 * @returns rcBusy when encountering a busy critical section in GC/R0.
    477  * @returns VERR_SEM_DESTROYED if the critical section is dead.
     483 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     484 *          during the operation.
    478485 *
    479486 * @param   pCritSect           The PDM critical section to enter.
     
    623630        uint32_t    i     = pVCpu->pdm.s.cQueuedCritSectLeaves++;
    624631        LogFlow(("PDMCritSectLeave: [%d]=%p => R3\n", i, pCritSect));
    625         AssertFatal(i < RT_ELEMENTS(pVCpu->pdm.s.apQueuedCritSectsLeaves));
    626         pVCpu->pdm.s.apQueuedCritSectsLeaves[i] = MMHyperCCToR3(pVM, pCritSect);
     632        AssertFatal(i < RT_ELEMENTS(pVCpu->pdm.s.apQueuedCritSectLeaves));
     633        pVCpu->pdm.s.apQueuedCritSectLeaves[i] = MMHyperCCToR3(pVM, pCritSect);
    627634        VMCPU_FF_SET(pVCpu, VMCPU_FF_PDM_CRITSECT);
    628635        VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3);
     
    634641    return VINF_SUCCESS;
    635642}
    636 
    637 
    638 #if defined(IN_RING3) || defined(IN_RING0)
    639 /**
    640  * Process the critical sections queued for ring-3 'leave'.
    641  *
    642  * @param   pVCpu         Pointer to the VMCPU.
    643  */
    644 VMMDECL(void) PDMCritSectFF(PVMCPU pVCpu)
    645 {
    646     Assert(pVCpu->pdm.s.cQueuedCritSectLeaves > 0);
    647 
    648     const RTUINT c = pVCpu->pdm.s.cQueuedCritSectLeaves;
    649     for (RTUINT i = 0; i < c; i++)
    650     {
    651 # ifdef IN_RING3
    652         PPDMCRITSECT pCritSect = pVCpu->pdm.s.apQueuedCritSectsLeaves[i];
    653 # else
    654         PPDMCRITSECT pCritSect = (PPDMCRITSECT)MMHyperR3ToCC(pVCpu->CTX_SUFF(pVM), pVCpu->pdm.s.apQueuedCritSectsLeaves[i]);
    655 # endif
    656 
    657         PDMCritSectLeave(pCritSect);
    658         LogFlow(("PDMR3CritSectFF: %p\n", pCritSect));
    659     }
    660 
    661     pVCpu->pdm.s.cQueuedCritSectLeaves = 0;
    662     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PDM_CRITSECT);
    663 }
    664 #endif /* IN_RING3 || IN_RING0 */
    665643
    666644
     
    748726    return RTCritSectGetRecursion(&pCritSect->s.Core);
    749727}
     728
  • trunk/src/VBox/VMM/VMMAll/PDMAllCritSectRw.cpp

    r45119 r45152  
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #define RTCRITSECTRW_WITHOUT_REMAPPING
    32 #define RTASSERT_QUIET
    33 #include <iprt/critsect.h>
    34 #include "internal/iprt.h"
    35 
     31#define LOG_GROUP LOG_GROUP_PDM//_CRITSECT
     32#include "PDMInternal.h"
     33#include <VBox/vmm/pdmcritsectrw.h>
     34#include <VBox/vmm/mm.h>
     35#include <VBox/vmm/vmm.h>
     36#include <VBox/vmm/vm.h>
     37#include <VBox/err.h>
     38#include <VBox/vmm/hm.h>
     39
     40#include <VBox/log.h>
    3641#include <iprt/asm.h>
     42#include <iprt/asm-amd64-x86.h>
    3743#include <iprt/assert.h>
    38 #include <iprt/err.h>
    39 #include <iprt/lockvalidator.h>
    40 #include <iprt/mem.h>
    41 #include <iprt/semaphore.h>
    42 #include <iprt/thread.h>
    43 
    44 #include "internal/magics.h"
    45 #include "internal/strict.h"
     44#ifdef IN_RING3
     45# include <iprt/lockvalidator.h>
     46# include <iprt/semaphore.h>
     47#endif
     48#if defined(IN_RING3) || defined(IN_RING0)
     49# include <iprt/thread.h>
     50#endif
    4651
    4752
     
    4954*   Defined Constants And Macros                                               *
    5055*******************************************************************************/
    51 /* Note! Using RTCSRW instead of RTCRITSECTRW to save space. */
    52 #define RTCSRW_CNT_BITS            15
    53 #define RTCSRW_CNT_MASK            UINT64_C(0x00007fff)
    54 
    55 #define RTCSRW_CNT_RD_SHIFT        0
    56 #define RTCSRW_CNT_RD_MASK         (RTCSRW_CNT_MASK << RTCSRW_CNT_RD_SHIFT)
    57 #define RTCSRW_CNT_WR_SHIFT        16
    58 #define RTCSRW_CNT_WR_MASK         (RTCSRW_CNT_MASK << RTCSRW_CNT_WR_SHIFT)
    59 #define RTCSRW_DIR_SHIFT           31
    60 #define RTCSRW_DIR_MASK            RT_BIT_64(RTCSRW_DIR_SHIFT)
    61 #define RTCSRW_DIR_READ            UINT64_C(0)
    62 #define RTCSRW_DIR_WRITE           UINT64_C(1)
    63 
    64 #define RTCSRW_WAIT_CNT_RD_SHIFT   32
    65 #define RTCSRW_WAIT_CNT_RD_MASK    (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_RD_SHIFT)
    66 //#define RTCSRW_WAIT_CNT_WR_SHIFT   48
    67 //#define RTCSRW_WAIT_CNT_WR_MASK    (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_WR_SHIFT)
    68 
    69 
    70 RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis)
    71 {
    72     return RTCritSectRwInitEx(pThis, 0, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectRw");
    73 }
    74 RT_EXPORT_SYMBOL(RTCritSectRwInit);
    75 
    76 
    77 RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags,
    78                                RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
    79 {
    80     int rc;
    81     AssertReturn(!(fFlags & ~( RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK
    82                               | RTCRITSECT_FLAGS_NOP )),
    83                  VERR_INVALID_PARAMETER);
    84 
    85     /*
    86      * Initialize the structure, allocate the lock validator stuff and sems.
    87      */
    88     pThis->u32Magic         = RTCRITSECTRW_MAGIC_DEAD;
    89     pThis->fNeedReset       = false;
    90     pThis->u64State         = 0;
    91     pThis->hNativeWriter    = NIL_RTNATIVETHREAD;
    92     pThis->cWriterReads     = 0;
    93     pThis->cWriteRecursions = 0;
    94     pThis->hEvtWrite        = NIL_RTSEMEVENT;
    95     pThis->hEvtRead         = NIL_RTSEMEVENTMULTI;
    96     pThis->pValidatorWrite  = NULL;
    97     pThis->pValidatorRead   = NULL;
    98 #if HC_ARCH_BITS == 32
    99     pThis->HCPtrPadding     = NIL_RTHCPTR;
    100 #endif
    101 
    102 #ifdef RTCRITSECTRW_STRICT
    103     bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL);
    104     if (!pszNameFmt)
    105     {
    106         static uint32_t volatile s_iAnon = 0;
    107         uint32_t i = ASMAtomicIncU32(&s_iAnon) - 1;
    108         rc = RTLockValidatorRecExclCreate(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
    109                                           fLVEnabled, "RTCritSectRw-%u", i);
    110         if (RT_SUCCESS(rc))
    111             rc = RTLockValidatorRecSharedCreate(&pThis->pValidatorRead, hClass, uSubClass, pThis,
    112                                                 false /*fSignaller*/, fLVEnabled, "RTCritSectRw-%u", i);
    113     }
    114     else
    115     {
    116         va_list va;
    117         va_start(va, pszNameFmt);
    118         rc = RTLockValidatorRecExclCreateV(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
    119                                            fLVEnabled, pszNameFmt, va);
    120         va_end(va);
    121         if (RT_SUCCESS(rc))
    122         {
    123             va_start(va, pszNameFmt);
    124             RTLockValidatorRecSharedCreateV(&pThis->pValidatorRead, hClass, uSubClass, pThis,
    125                                             false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
    126             va_end(va);
    127         }
    128     }
    129     if (RT_SUCCESS(rc))
    130         rc = RTLockValidatorRecMakeSiblings(&pThis->pValidatorWrite->Core, &pThis->pValidatorRead->Core);
    131 
    132     if (RT_SUCCESS(rc))
    133 #endif
    134     {
    135         rc = RTSemEventMultiCreate(&pThis->hEvtRead);
    136         if (RT_SUCCESS(rc))
    137         {
    138             rc = RTSemEventCreate(&pThis->hEvtWrite);
    139             if (RT_SUCCESS(rc))
    140             {
    141                 pThis->u32Magic = RTCRITSECTRW_MAGIC;
    142                 return VINF_SUCCESS;
    143             }
    144             RTSemEventMultiDestroy(pThis->hEvtRead);
    145         }
    146     }
    147 
    148 #ifdef RTCRITSECTRW_STRICT
    149     RTLockValidatorRecSharedDestroy(&pThis->pValidatorRead);
    150     RTLockValidatorRecExclDestroy(&pThis->pValidatorWrite);
    151 #endif
    152     return rc;
    153 }
    154 RT_EXPORT_SYMBOL(RTCritSectRwInitEx);
    155 
    156 
    157 RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass)
     56/** The number loops to spin for shared access in ring-3. */
     57#define PDMCRITSECTRW_SHRD_SPIN_COUNT_R3       20
     58/** The number loops to spin for shared access in ring-0. */
     59#define PDMCRITSECTRW_SHRD_SPIN_COUNT_R0       128
     60/** The number loops to spin for shared access in the raw-mode context. */
     61#define PDMCRITSECTRW_SHRD_SPIN_COUNT_RC       128
     62
     63/** The number loops to spin for exclusive access in ring-3. */
     64#define PDMCRITSECTRW_EXCL_SPIN_COUNT_R3       20
     65/** The number loops to spin for exclusive access in ring-0. */
     66#define PDMCRITSECTRW_EXCL_SPIN_COUNT_R0       256
     67/** The number loops to spin for exclusive access in the raw-mode context. */
     68#define PDMCRITSECTRW_EXCL_SPIN_COUNT_RC       256
     69
     70
     71/* Undefine the automatic VBOX_STRICT API mappings. */
     72#undef PDMCritSectRwEnterExcl
     73#undef PDMCritSectRwTryEnterExcl
     74#undef PDMCritSectRwEnterShared
     75#undef PDMCritSectRwTryEnterShared
     76
     77
     78/**
     79 * Gets the ring-3 native thread handle of the calling thread.
     80 *
     81 * @returns native thread handle (ring-3).
     82 * @param   pThis       The read/write critical section.  This is only used in
     83 *                      R0 and RC.
     84 */
     85DECL_FORCE_INLINE(RTNATIVETHREAD) pdmCritSectRwGetNativeSelf(PCPDMCRITSECTRW pThis)
     86{
     87#ifdef IN_RING3
     88    NOREF(pThis);
     89    RTNATIVETHREAD  hNativeSelf = RTThreadNativeSelf();
     90#else
     91    AssertMsgReturn(pThis->s.Core.u32Magic == RTCRITSECT_MAGIC, ("%RX32\n", pThis->s.Core.u32Magic),
     92                    NIL_RTNATIVETHREAD);
     93    PVM             pVM         = pThis->s.CTX_SUFF(pVM);   AssertPtr(pVM);
     94    PVMCPU          pVCpu       = VMMGetCpu(pVM);           AssertPtr(pVCpu);
     95    RTNATIVETHREAD  hNativeSelf = pVCpu->hNativeThread;     Assert(hNativeSelf != NIL_RTNATIVETHREAD);
     96#endif
     97    return hNativeSelf;
     98}
     99
     100
     101
     102
     103
     104#ifdef IN_RING3
     105/**
     106 * Changes the lock validator sub-class of the read/write critical section.
     107 *
     108 * It is recommended to try make sure that nobody is using this critical section
     109 * while changing the value.
     110 *
     111 * @returns The old sub-class.  RTLOCKVAL_SUB_CLASS_INVALID is returns if the
     112 *          lock validator isn't compiled in or either of the parameters are
     113 *          invalid.
     114 * @param   pThis           Pointer to the read/write critical section.
     115 * @param   uSubClass       The new sub-class value.
     116 */
     117VMMDECL(uint32_t) PDMR3CritSectRwSetSubClass(PPDMCRITSECTRW pThis, uint32_t uSubClass)
    158118{
    159119    AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
    160     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
    161 #ifdef RTCRITSECTRW_STRICT
    162     AssertReturn(!(pThis->fFlags & RTCRITSECT_FLAGS_NOP), RTLOCKVAL_SUB_CLASS_INVALID);
    163 
    164     RTLockValidatorRecSharedSetSubClass(pThis->pValidatorRead, uSubClass);
    165     return RTLockValidatorRecExclSetSubClass(pThis->pValidatorWrite, uSubClass);
    166 #else
     120    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
     121# ifdef PDMCRITSECTRW_STRICT
     122    AssertReturn(!(pThis->s.Core.fFlags & RTCRITSECT_FLAGS_NOP), RTLOCKVAL_SUB_CLASS_INVALID);
     123
     124    RTLockValidatorRecSharedSetSubClass(pThis->s.Core.pValidatorRead, uSubClass);
     125    return RTLockValidatorRecExclSetSubClass(pThis->s.Core.pValidatorWrite, uSubClass);
     126# else
    167127    NOREF(uSubClass);
    168128    return RTLOCKVAL_SUB_CLASS_INVALID;
    169 #endif
    170 }
    171 RT_EXPORT_SYMBOL(RTCritSectRwSetSubClass);
    172 
    173 
    174 static int rtCritSectRwEnterShared(PRTCRITSECTRW pThis, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
     129# endif
     130}
     131#endif /* IN_RING3 */
     132
     133
     134static int pdmCritSectRwEnterShared(PPDMCRITSECTRW pThis, int rcBusy, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
    175135{
    176136    /*
     
    178138     */
    179139    AssertPtr(pThis);
    180     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
    181 
    182 #ifdef RTCRITSECTRW_STRICT
     140    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
     141
     142#ifdef PDMCRITSECTRW_STRICT
    183143    RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
    184144    if (!fTryOnly)
     
    186146        int            rc9;
    187147        RTNATIVETHREAD hNativeWriter;
    188         ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
    189         if (hNativeWriter != NIL_RTTHREAD && hNativeWriter == RTThreadNativeSelf())
    190             rc9 = RTLockValidatorRecExclCheckOrder(pThis->pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
     148        ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
     149        if (hNativeWriter != NIL_RTTHREAD && hNativeWriter == pdmCritSectRwGetNativeSelf(pThis))
     150            rc9 = RTLockValidatorRecExclCheckOrder(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
    191151        else
    192             rc9 = RTLockValidatorRecSharedCheckOrder(pThis->pValidatorRead, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
     152            rc9 = RTLockValidatorRecSharedCheckOrder(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
    193153        if (RT_FAILURE(rc9))
    194154            return rc9;
     
    199159     * Get cracking...
    200160     */
    201     uint64_t u64State    = ASMAtomicReadU64(&pThis->u64State);
     161    uint64_t u64State    = ASMAtomicReadU64(&pThis->s.Core.u64State);
    202162    uint64_t u64OldState = u64State;
    203163
     
    212172            u64State &= ~RTCSRW_CNT_RD_MASK;
    213173            u64State |= c << RTCSRW_CNT_RD_SHIFT;
    214             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
    215             {
    216 #ifdef RTCRITSECTRW_STRICT
    217                 RTLockValidatorRecSharedAddOwner(pThis->pValidatorRead, hThreadSelf, pSrcPos);
     174            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
     175            {
     176#ifdef PDMCRITSECTRW_STRICT
     177                RTLockValidatorRecSharedAddOwner(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos);
    218178#endif
    219179                break;
     
    225185            u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
    226186            u64State |= (UINT64_C(1) << RTCSRW_CNT_RD_SHIFT) | (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT);
    227             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
    228             {
    229                 Assert(!pThis->fNeedReset);
    230 #ifdef RTCRITSECTRW_STRICT
    231                 RTLockValidatorRecSharedAddOwner(pThis->pValidatorRead, hThreadSelf, pSrcPos);
     187            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
     188            {
     189                Assert(!pThis->s.Core.fNeedReset);
     190#ifdef PDMCRITSECTRW_STRICT
     191                RTLockValidatorRecSharedAddOwner(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos);
    232192#endif
    233193                break;
     
    237197        {
    238198            /* Is the writer perhaps doing a read recursion? */
    239             RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
     199            RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
    240200            RTNATIVETHREAD hNativeWriter;
    241             ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
     201            ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
    242202            if (hNativeSelf == hNativeWriter)
    243203            {
    244 #ifdef RTCRITSECTRW_STRICT
    245                 int rc9 = RTLockValidatorRecExclRecursionMixed(pThis->pValidatorWrite, &pThis->pValidatorRead->Core, pSrcPos);
     204#ifdef PDMCRITSECTRW_STRICT
     205                int rc9 = RTLockValidatorRecExclRecursionMixed(pThis->s.Core.pValidatorWrite, &pThis->s.Core.pValidatorRead->Core, pSrcPos);
    246206                if (RT_FAILURE(rc9))
    247207                    return rc9;
    248208#endif
    249                 Assert(pThis->cWriterReads < UINT32_MAX / 2);
    250                 ASMAtomicIncU32(&pThis->cWriterReads);
     209                Assert(pThis->s.Core.cWriterReads < UINT32_MAX / 2);
     210                ASMAtomicIncU32(&pThis->s.Core.cWriterReads);
    251211                return VINF_SUCCESS; /* don't break! */
    252212            }
     
    269229            u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
    270230
    271             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     231            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    272232            {
    273233                for (uint32_t iLoop = 0; ; iLoop++)
    274234                {
    275235                    int rc;
    276 #ifdef RTCRITSECTRW_STRICT
    277                     rc = RTLockValidatorRecSharedCheckBlocking(pThis->pValidatorRead, hThreadSelf, pSrcPos, true,
     236#ifdef PDMCRITSECTRW_STRICT
     237                    rc = RTLockValidatorRecSharedCheckBlocking(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos, true,
    278238                                                               RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_READ, false);
    279239                    if (RT_SUCCESS(rc))
     
    283243#endif
    284244                    {
    285                         rc = RTSemEventMultiWait(pThis->hEvtRead, RT_INDEFINITE_WAIT);
     245                        do
     246                            rc = SUPSemEventMultiWaitNoResume(pThis->s.CTX_SUFF(pVM)->pSession,
     247                                                              (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead,
     248                                                              RT_INDEFINITE_WAIT);
     249                        while (rc == VERR_INTERRUPTED && pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC);
    286250                        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
    287                         if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
     251                        if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    288252                            return VERR_SEM_DESTROYED;
    289253                    }
     
    293257                        for (;;)
    294258                        {
    295                             u64OldState = u64State = ASMAtomicReadU64(&pThis->u64State);
     259                            u64OldState = u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    296260                            c = (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT; Assert(c > 0);
    297261                            c--;
     
    300264                            u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_WAIT_CNT_RD_MASK);
    301265                            u64State |= (c << RTCSRW_CNT_RD_SHIFT) | (cWait << RTCSRW_WAIT_CNT_RD_SHIFT);
    302                             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     266                            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    303267                                break;
    304268                        }
     
    306270                    }
    307271
    308                     Assert(pThis->fNeedReset);
    309                     u64State = ASMAtomicReadU64(&pThis->u64State);
     272                    Assert(pThis->s.Core.fNeedReset);
     273                    u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    310274                    if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
    311275                        break;
     
    324288                    u64State |= cWait << RTCSRW_WAIT_CNT_RD_SHIFT;
    325289
    326                     if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     290                    if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    327291                    {
    328292                        if (cWait == 0)
    329293                        {
    330                             if (ASMAtomicXchgBool(&pThis->fNeedReset, false))
     294                            if (ASMAtomicXchgBool(&pThis->s.Core.fNeedReset, false))
    331295                            {
    332                                 int rc = RTSemEventMultiReset(pThis->hEvtRead);
     296                                int rc = SUPSemEventMultiReset(pThis->s.CTX_SUFF(pVM)->pSession,
     297                                                               (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead);
    333298                                AssertRCReturn(rc, rc);
    334299                            }
     
    336301                        break;
    337302                    }
    338                     u64State = ASMAtomicReadU64(&pThis->u64State);
     303                    u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    339304                }
    340305
    341 #ifdef RTCRITSECTRW_STRICT
    342                 RTLockValidatorRecSharedAddOwner(pThis->pValidatorRead, hThreadSelf, pSrcPos);
     306#ifdef PDMCRITSECTRW_STRICT
     307                RTLockValidatorRecSharedAddOwner(pThis->s.Core.pValidatorRead, hThreadSelf, pSrcPos);
    343308#endif
    344309                break;
     
    346311        }
    347312
    348         if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
     313        if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    349314            return VERR_SEM_DESTROYED;
    350315
    351316        ASMNopPause();
    352         u64State = ASMAtomicReadU64(&pThis->u64State);
     317        u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    353318        u64OldState = u64State;
    354319    }
    355320
    356321    /* got it! */
    357     Assert((ASMAtomicReadU64(&pThis->u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT));
     322    Assert((ASMAtomicReadU64(&pThis->s.Core.u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT));
    358323    return VINF_SUCCESS;
    359324
     
    361326
    362327
    363 RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis)
    364 {
    365 #ifndef RTCRITSECTRW_STRICT
    366     return rtCritSectRwEnterShared(pThis, NULL, false /*fTryOnly*/);
     328/**
     329 * Enter a critical section with shared (read) access.
     330 *
     331 * @returns VBox status code.
     332 * @retval  VINF_SUCCESS on success.
     333 * @retval  @a rcBusy if in ring-0 or raw-mode context and it is busy.
     334 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     335 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     336 *          during the operation.
     337 *
     338 * @param   pThis       Pointer to the read/write critical section.
     339 * @param   rcBusy      The status code to return when we're in RC or R0 and the
     340 *                      section is busy.   Pass VINF_SUCCESS to acquired the
     341 *                      critical section thru a ring-3 call if necessary.
     342 * @param   uId         Where we're entering the section.
     343 * @param   pszFile     The source position - file.
     344 * @param   iLine       The source position - line.
     345 * @param   pszFunction The source position - function.
     346 * @sa      PDMCritSectRwEnterSharedDebug, PDMCritSectRwTryEnterShared,
     347 *          PDMCritSectRwTryEnterSharedDebug, PDMCritSectRwLeaveShared,
     348 *          RTCritSectRwEnterShared.
     349 */
     350VMMDECL(int) PDMCritSectRwEnterShared(PPDMCRITSECTRW pThis, int rcBusy)
     351{
     352#ifndef PDMCRITSECTRW_STRICT
     353    return pdmCritSectRwEnterShared(pThis, rcBusy, NULL, false /*fTryOnly*/);
    367354#else
    368355    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
    369     return rtCritSectRwEnterShared(pThis, &SrcPos, false /*fTryOnly*/);
    370 #endif
    371 }
    372 RT_EXPORT_SYMBOL(RTCritSectRwEnterShared);
    373 
    374 
    375 RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     356    return pdmCritSectRwEnterShared(pThis, rcBusy, &SrcPos, false /*fTryOnly*/);
     357#endif
     358}
     359
     360
     361/**
     362 * Enter a critical section with shared (read) access.
     363 *
     364 * @returns VBox status code.
     365 * @retval  VINF_SUCCESS on success.
     366 * @retval  @a rcBusy if in ring-0 or raw-mode context and it is busy.
     367 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     368 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     369 *          during the operation.
     370 *
     371 * @param   pThis       Pointer to the read/write critical section.
     372 * @param   rcBusy      The status code to return when we're in RC or R0 and the
     373 *                      section is busy.   Pass VINF_SUCCESS to acquired the
     374 *                      critical section thru a ring-3 call if necessary.
     375 * @param   uId         Where we're entering the section.
     376 * @param   pszFile     The source position - file.
     377 * @param   iLine       The source position - line.
     378 * @param   pszFunction The source position - function.
     379 * @sa      PDMCritSectRwEnterShared, PDMCritSectRwTryEnterShared,
     380 *          PDMCritSectRwTryEnterSharedDebug, PDMCritSectRwLeaveShared,
     381 *          RTCritSectRwEnterSharedDebug.
     382 */
     383VMMDECL(int) PDMCritSectRwEnterSharedDebug(PPDMCRITSECTRW pThis, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
    376384{
    377385    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
    378     return rtCritSectRwEnterShared(pThis, &SrcPos, false /*fTryOnly*/);
    379 }
    380 RT_EXPORT_SYMBOL(RTCritSectRwEnterSharedDebug);
    381 
    382 
    383 RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis)
    384 {
    385 #ifndef RTCRITSECTRW_STRICT
    386     return rtCritSectRwEnterShared(pThis, NULL, true /*fTryOnly*/);
     386    return pdmCritSectRwEnterShared(pThis, rcBusy, &SrcPos, false /*fTryOnly*/);
     387}
     388
     389
     390/**
     391 * Try enter a critical section with shared (read) access.
     392 *
     393 * @returns VBox status code.
     394 * @retval  VINF_SUCCESS on success.
     395 * @retval  VERR_SEM_BUSY if the critsect was owned.
     396 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     397 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     398 *          during the operation.
     399 *
     400 * @param   pThis       Pointer to the read/write critical section.
     401 * @param   uId         Where we're entering the section.
     402 * @param   pszFile     The source position - file.
     403 * @param   iLine       The source position - line.
     404 * @param   pszFunction The source position - function.
     405 * @sa      PDMCritSectRwTryEnterSharedDebug, PDMCritSectRwEnterShared,
     406 *          PDMCritSectRwEnterSharedDebug, PDMCritSectRwLeaveShared,
     407 *          RTCritSectRwTryEnterShared.
     408 */
     409VMMDECL(int) PDMCritSectRwTryEnterShared(PPDMCRITSECTRW pThis)
     410{
     411#ifndef PDMCRITSECTRW_STRICT
     412    return pdmCritSectRwEnterShared(pThis, VERR_SEM_BUSY, NULL, true /*fTryOnly*/);
    387413#else
    388414    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
    389     return rtCritSectRwEnterShared(pThis, &SrcPos, true /*fTryOnly*/);
    390 #endif
    391 }
    392 RT_EXPORT_SYMBOL(RTCritSectRwEnterShared);
    393 
    394 
    395 RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     415    return pdmCritSectRwEnterShared(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryOnly*/);
     416#endif
     417}
     418
     419
     420/**
     421 * Try enter a critical section with shared (read) access.
     422 *
     423 * @returns VBox status code.
     424 * @retval  VINF_SUCCESS on success.
     425 * @retval  VERR_SEM_BUSY if the critsect was owned.
     426 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     427 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     428 *          during the operation.
     429 *
     430 * @param   pThis       Pointer to the read/write critical section.
     431 * @param   uId         Where we're entering the section.
     432 * @param   pszFile     The source position - file.
     433 * @param   iLine       The source position - line.
     434 * @param   pszFunction The source position - function.
     435 * @sa      PDMCritSectRwTryEnterShared, PDMCritSectRwEnterShared,
     436 *          PDMCritSectRwEnterSharedDebug, PDMCritSectRwLeaveShared,
     437 *          RTCritSectRwTryEnterSharedDebug.
     438 */
     439VMMDECL(int) PDMCritSectRwTryEnterSharedDebug(PPDMCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
    396440{
    397441    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
    398     return rtCritSectRwEnterShared(pThis, &SrcPos, true /*fTryOnly*/);
    399 }
    400 RT_EXPORT_SYMBOL(RTCritSectRwEnterSharedDebug);
    401 
    402 
    403 
    404 RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis)
     442    return pdmCritSectRwEnterShared(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryOnly*/);
     443}
     444
     445
     446/**
     447 * Leave a critical section held with shared access.
     448 *
     449 * @returns VBox status code.
     450 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     451 *          during the operation.
     452 * @param   pThis       Pointer to the read/write critical section.
     453 * @sa      PDMCritSectRwEnterShared, PDMCritSectRwTryEnterShared,
     454 *          PDMCritSectRwEnterSharedDebug, PDMCritSectRwTryEnterSharedDebug,
     455 *          PDMCritSectRwLeaveExcl, RTCritSectRwLeaveShared.
     456 */
     457VMMDECL(int) PDMCritSectRwLeaveShared(PPDMCRITSECTRW pThis)
    405458{
    406459    /*
     
    408461     */
    409462    AssertPtr(pThis);
    410     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
     463    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
    411464
    412465    /*
    413466     * Check the direction and take action accordingly.
    414467     */
    415     uint64_t u64State    = ASMAtomicReadU64(&pThis->u64State);
     468    uint64_t u64State    = ASMAtomicReadU64(&pThis->s.Core.u64State);
    416469    uint64_t u64OldState = u64State;
    417470    if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
    418471    {
    419 #ifdef RTCRITSECTRW_STRICT
    420         int rc9 = RTLockValidatorRecSharedCheckAndRelease(pThis->pValidatorRead, NIL_RTTHREAD);
     472#ifdef PDMCRITSECTRW_STRICT
     473        int rc9 = RTLockValidatorRecSharedCheckAndRelease(pThis->s.Core.pValidatorRead, NIL_RTTHREAD);
    421474        if (RT_FAILURE(rc9))
    422475            return rc9;
     
    434487                u64State &= ~RTCSRW_CNT_RD_MASK;
    435488                u64State |= c << RTCSRW_CNT_RD_SHIFT;
    436                 if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     489                if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    437490                    break;
    438491            }
     
    442495                u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_DIR_MASK);
    443496                u64State |= RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT;
    444                 if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     497                if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    445498                {
    446                     int rc = RTSemEventSignal(pThis->hEvtWrite);
     499                    int rc = SUPSemEventSignal(pThis->s.CTX_SUFF(pVM)->pSession, (SUPSEMEVENT)pThis->s.Core.hEvtWrite);
    447500                    AssertRC(rc);
    448501                    break;
     
    451504
    452505            ASMNopPause();
    453             u64State = ASMAtomicReadU64(&pThis->u64State);
     506            u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    454507            u64OldState = u64State;
    455508        }
     
    457510    else
    458511    {
    459         RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
     512        RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
    460513        RTNATIVETHREAD hNativeWriter;
    461         ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
     514        ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
    462515        AssertReturn(hNativeSelf == hNativeWriter, VERR_NOT_OWNER);
    463         AssertReturn(pThis->cWriterReads > 0, VERR_NOT_OWNER);
    464 #ifdef RTCRITSECTRW_STRICT
    465         int rc = RTLockValidatorRecExclUnwindMixed(pThis->pValidatorWrite, &pThis->pValidatorRead->Core);
     516        AssertReturn(pThis->s.Core.cWriterReads > 0, VERR_NOT_OWNER);
     517#ifdef PDMCRITSECTRW_STRICT
     518        int rc = RTLockValidatorRecExclUnwindMixed(pThis->s.Core.pValidatorWrite, &pThis->s.Core.pValidatorRead->Core);
    466519        if (RT_FAILURE(rc))
    467520            return rc;
    468521#endif
    469         ASMAtomicDecU32(&pThis->cWriterReads);
     522        ASMAtomicDecU32(&pThis->s.Core.cWriterReads);
    470523    }
    471524
    472525    return VINF_SUCCESS;
    473526}
    474 RT_EXPORT_SYMBOL(RTCritSectRwLeaveShared);
    475 
    476 
    477 static int rtCritSectRwEnterExcl(PRTCRITSECTRW pThis, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
     527
     528
     529static int pdmCritSectRwEnterExcl(PPDMCRITSECTRW pThis, int rcBusy, PCRTLOCKVALSRCPOS pSrcPos, bool fTryOnly)
    478530{
    479531    /*
     
    481533     */
    482534    AssertPtr(pThis);
    483     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
    484 
    485 #ifdef RTCRITSECTRW_STRICT
     535    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
     536
     537#ifdef PDMCRITSECTRW_STRICT
    486538    RTTHREAD hThreadSelf = NIL_RTTHREAD;
    487539    if (!fTryOnly)
    488540    {
    489541        hThreadSelf = RTThreadSelfAutoAdopt();
    490         int rc9 = RTLockValidatorRecExclCheckOrder(pThis->pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
     542        int rc9 = RTLockValidatorRecExclCheckOrder(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
    491543        if (RT_FAILURE(rc9))
    492544            return rc9;
     
    497549     * Check if we're already the owner and just recursing.
    498550     */
    499     RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
     551    RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
    500552    RTNATIVETHREAD hNativeWriter;
    501     ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
     553    ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
    502554    if (hNativeSelf == hNativeWriter)
    503555    {
    504         Assert((ASMAtomicReadU64(&pThis->u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
    505 #ifdef RTCRITSECTRW_STRICT
    506         int rc9 = RTLockValidatorRecExclRecursion(pThis->pValidatorWrite, pSrcPos);
     556        Assert((ASMAtomicReadU64(&pThis->s.Core.u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
     557#ifdef PDMCRITSECTRW_STRICT
     558        int rc9 = RTLockValidatorRecExclRecursion(pThis->s.Core.pValidatorWrite, pSrcPos);
    507559        if (RT_FAILURE(rc9))
    508560            return rc9;
    509561#endif
    510         Assert(pThis->cWriteRecursions < UINT32_MAX / 2);
    511         ASMAtomicIncU32(&pThis->cWriteRecursions);
     562        Assert(pThis->s.Core.cWriteRecursions < UINT32_MAX / 2);
     563        ASMAtomicIncU32(&pThis->s.Core.cWriteRecursions);
    512564        return VINF_SUCCESS;
    513565    }
     
    516568     * Get cracking.
    517569     */
    518     uint64_t u64State    = ASMAtomicReadU64(&pThis->u64State);
     570    uint64_t u64State    = ASMAtomicReadU64(&pThis->s.Core.u64State);
    519571    uint64_t u64OldState = u64State;
    520572
     
    530582            u64State &= ~RTCSRW_CNT_WR_MASK;
    531583            u64State |= c << RTCSRW_CNT_WR_SHIFT;
    532             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     584            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    533585                break;
    534586        }
     
    538590            u64State &= ~(RTCSRW_CNT_RD_MASK | RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
    539591            u64State |= (UINT64_C(1) << RTCSRW_CNT_WR_SHIFT) | (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT);
    540             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     592            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    541593                break;
    542594        }
     
    552604            u64State &= ~RTCSRW_CNT_WR_MASK;
    553605            u64State |= c << RTCSRW_CNT_WR_SHIFT;
    554             if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     606            if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    555607                break;
    556608        }
    557609
    558         if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
     610        if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    559611            return VERR_SEM_DESTROYED;
    560612
    561613        ASMNopPause();
    562         u64State = ASMAtomicReadU64(&pThis->u64State);
     614        u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    563615        u64OldState = u64State;
    564616    }
     
    572624                  || fTryOnly);
    573625    if (fDone)
    574         ASMAtomicCmpXchgHandle(&pThis->hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
     626        ASMAtomicCmpXchgHandle(&pThis->s.Core.hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
    575627    if (!fDone)
    576628    {
     
    581633        {
    582634            int rc;
    583 #ifdef RTCRITSECTRW_STRICT
     635#ifdef PDMCRITSECTRW_STRICT
    584636            if (!fTryOnly)
    585637            {
    586638                if (hThreadSelf == NIL_RTTHREAD)
    587639                    hThreadSelf = RTThreadSelfAutoAdopt();
    588                 rc = RTLockValidatorRecExclCheckBlocking(pThis->pValidatorWrite, hThreadSelf, pSrcPos, true,
     640                rc = RTLockValidatorRecExclCheckBlocking(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, true,
    589641                                                         RT_INDEFINITE_WAIT, RTTHREADSTATE_RW_WRITE, false);
    590642            }
     
    597649#endif
    598650            {
    599                 rc = RTSemEventWait(pThis->hEvtWrite, RT_INDEFINITE_WAIT);
     651                do
     652                    rc = SUPSemEventWaitNoResume(pThis->s.CTX_SUFF(pVM)->pSession,
     653                                                 (SUPSEMEVENT)pThis->s.Core.hEvtWrite,
     654                                                 RT_INDEFINITE_WAIT);
     655                while (rc == VERR_INTERRUPTED && pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC);
    600656                RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
    601                 if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
     657                if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    602658                    return VERR_SEM_DESTROYED;
    603659            }
     
    607663                for (;;)
    608664                {
    609                     u64OldState = u64State = ASMAtomicReadU64(&pThis->u64State);
     665                    u64OldState = u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    610666                    uint64_t c = (u64State & RTCSRW_CNT_WR_MASK) >> RTCSRW_CNT_WR_SHIFT; Assert(c > 0);
    611667                    c--;
    612668                    u64State &= ~RTCSRW_CNT_WR_MASK;
    613669                    u64State |= c << RTCSRW_CNT_WR_SHIFT;
    614                     if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     670                    if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    615671                        break;
    616672                }
     
    618674            }
    619675
    620             u64State = ASMAtomicReadU64(&pThis->u64State);
     676            u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    621677            if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT))
    622678            {
    623                 ASMAtomicCmpXchgHandle(&pThis->hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
     679                ASMAtomicCmpXchgHandle(&pThis->s.Core.hNativeWriter, hNativeSelf, NIL_RTNATIVETHREAD, fDone);
    624680                if (fDone)
    625681                    break;
     
    632688     * Got it!
    633689     */
    634     Assert((ASMAtomicReadU64(&pThis->u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
    635     ASMAtomicWriteU32(&pThis->cWriteRecursions, 1);
    636     Assert(pThis->cWriterReads == 0);
    637 #ifdef RTCRITSECTRW_STRICT
    638     RTLockValidatorRecExclSetOwner(pThis->pValidatorWrite, hThreadSelf, pSrcPos, true);
     690    Assert((ASMAtomicReadU64(&pThis->s.Core.u64State) & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT));
     691    ASMAtomicWriteU32(&pThis->s.Core.cWriteRecursions, 1);
     692    Assert(pThis->s.Core.cWriterReads == 0);
     693#ifdef PDMCRITSECTRW_STRICT
     694    RTLockValidatorRecExclSetOwner(pThis->s.Core.pValidatorWrite, hThreadSelf, pSrcPos, true);
    639695#endif
    640696
     
    643699
    644700
    645 RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis)
    646 {
    647 #ifndef RTCRITSECTRW_STRICT
    648     return rtCritSectRwEnterExcl(pThis, NULL, false /*fTryAgain*/);
     701/**
     702 * Try enter a critical section with exclusive (write) access.
     703 *
     704 * @returns VBox status code.
     705 * @retval  VINF_SUCCESS on success.
     706 * @retval  @a rcBusy if in ring-0 or raw-mode context and it is busy.
     707 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     708 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     709 *          during the operation.
     710 *
     711 * @param   pThis       Pointer to the read/write critical section.
     712 * @param   rcBusy      The status code to return when we're in RC or R0 and the
     713 *                      section is busy.   Pass VINF_SUCCESS to acquired the
     714 *                      critical section thru a ring-3 call if necessary.
     715 * @sa      PDMCritSectRwEnterExclDebug, PDMCritSectRwTryEnterExcl,
     716 *          PDMCritSectRwTryEnterExclDebug,
     717 *          PDMCritSectEnterDebug, PDMCritSectEnter,
     718 * RTCritSectRwEnterExcl.
     719 */
     720VMMDECL(int) PDMCritSectRwEnterExcl(PPDMCRITSECTRW pThis, int rcBusy)
     721{
     722#ifndef PDMCRITSECTRW_STRICT
     723    return pdmCritSectRwEnterExcl(pThis, rcBusy, NULL, false /*fTryAgain*/);
    649724#else
    650725    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
    651     return rtCritSectRwEnterExcl(pThis, &SrcPos, false /*fTryAgain*/);
    652 #endif
    653 }
    654 RT_EXPORT_SYMBOL(RTCritSectRwEnterExcl);
    655 
    656 
    657 RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     726    return pdmCritSectRwEnterExcl(pThis, rcBusy, &SrcPos, false /*fTryAgain*/);
     727#endif
     728}
     729
     730
     731/**
     732 * Try enter a critical section with exclusive (write) access.
     733 *
     734 * @returns VBox status code.
     735 * @retval  VINF_SUCCESS on success.
     736 * @retval  @a rcBusy if in ring-0 or raw-mode context and it is busy.
     737 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     738 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     739 *          during the operation.
     740 *
     741 * @param   pThis       Pointer to the read/write critical section.
     742 * @param   rcBusy      The status code to return when we're in RC or R0 and the
     743 *                      section is busy.   Pass VINF_SUCCESS to acquired the
     744 *                      critical section thru a ring-3 call if necessary.
     745 * @param   uId         Where we're entering the section.
     746 * @param   pszFile     The source position - file.
     747 * @param   iLine       The source position - line.
     748 * @param   pszFunction The source position - function.
     749 * @sa      PDMCritSectRwEnterExcl, PDMCritSectRwTryEnterExcl,
     750 *          PDMCritSectRwTryEnterExclDebug,
     751 *          PDMCritSectEnterDebug, PDMCritSectEnter,
     752 *          RTCritSectRwEnterExclDebug.
     753 */
     754VMMDECL(int) PDMCritSectRwEnterExclDebug(PPDMCRITSECTRW pThis, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
    658755{
    659756    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
    660     return rtCritSectRwEnterExcl(pThis, &SrcPos, false /*fTryAgain*/);
    661 }
    662 RT_EXPORT_SYMBOL(RTCritSectRwEnterExclDebug);
    663 
    664 
    665 RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis)
    666 {
    667 #ifndef RTCRITSECTRW_STRICT
    668     return rtCritSectRwEnterExcl(pThis, NULL, true /*fTryAgain*/);
     757    return pdmCritSectRwEnterExcl(pThis, rcBusy, &SrcPos, false /*fTryAgain*/);
     758}
     759
     760
     761/**
     762 * Try enter a critical section with exclusive (write) access.
     763 *
     764 * @retval  VINF_SUCCESS on success.
     765 * @retval  VERR_SEM_BUSY if the critsect was owned.
     766 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     767 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     768 *          during the operation.
     769 *
     770 * @param   pThis       Pointer to the read/write critical section.
     771 * @sa      PDMCritSectRwEnterExcl, PDMCritSectRwTryEnterExclDebug,
     772 *          PDMCritSectRwEnterExclDebug,
     773 *          PDMCritSectTryEnter, PDMCritSectTryEnterDebug,
     774 *          RTCritSectRwTryEnterExcl.
     775 */
     776VMMDECL(int) PDMCritSectRwTryEnterExcl(PPDMCRITSECTRW pThis)
     777{
     778#ifndef PDMCRITSECTRW_STRICT
     779    return pdmCritSectRwEnterExcl(pThis, VERR_SEM_BUSY, NULL, true /*fTryAgain*/);
    669780#else
    670781    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
    671     return rtCritSectRwEnterExcl(pThis, &SrcPos, true /*fTryAgain*/);
    672 #endif
    673 }
    674 RT_EXPORT_SYMBOL(RTCritSectRwTryEnterExcl);
    675 
    676 
    677 RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     782    return pdmCritSectRwEnterExcl(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryAgain*/);
     783#endif
     784}
     785
     786
     787/**
     788 * Try enter a critical section with exclusive (write) access.
     789 *
     790 * @retval  VINF_SUCCESS on success.
     791 * @retval  VERR_SEM_BUSY if the critsect was owned.
     792 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     793 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     794 *          during the operation.
     795 *
     796 * @param   pThis       Pointer to the read/write critical section.
     797 * @param   uId         Where we're entering the section.
     798 * @param   pszFile     The source position - file.
     799 * @param   iLine       The source position - line.
     800 * @param   pszFunction The source position - function.
     801 * @sa      PDMCritSectRwTryEnterExcl, PDMCritSectRwEnterExcl,
     802 *          PDMCritSectRwEnterExclDebug,
     803 *          PDMCritSectTryEnterDebug, PDMCritSectTryEnter,
     804 *          RTCritSectRwTryEnterExclDebug.
     805 */
     806VMMDECL(int) PDMCritSectRwTryEnterExclDebug(PPDMCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL)
    678807{
    679808    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
    680     return rtCritSectRwEnterExcl(pThis, &SrcPos, true /*fTryAgain*/);
    681 }
    682 RT_EXPORT_SYMBOL(RTCritSectRwTryEnterExclDebug);
    683 
    684 
    685 RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis)
     809    return pdmCritSectRwEnterExcl(pThis, VERR_SEM_BUSY, &SrcPos, true /*fTryAgain*/);
     810}
     811
     812
     813/**
     814 * Leave a critical section held exclusively.
     815 *
     816 * @returns VBox status code.
     817 * @retval  VERR_SEM_DESTROYED if the critical section is delete before or
     818 *          during the operation.
     819 * @param   pThis       Pointer to the read/write critical section.
     820 * @sa      PDMCritSectRwLeaveShared, RTCritSectRwLeaveExcl.
     821 */
     822VMMDECL(int) PDMCritSectRwLeaveExcl(PPDMCRITSECTRW pThis)
    686823{
    687824    /*
     
    689826     */
    690827    AssertPtr(pThis);
    691     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
    692 
    693     RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
     828    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, VERR_SEM_DESTROYED);
     829
     830    RTNATIVETHREAD hNativeSelf = pdmCritSectRwGetNativeSelf(pThis);
    694831    RTNATIVETHREAD hNativeWriter;
    695     ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
     832    ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
    696833    AssertReturn(hNativeSelf == hNativeWriter, VERR_NOT_OWNER);
    697834
     
    699836     * Unwind a recursion.
    700837     */
    701     if (pThis->cWriteRecursions == 1)
     838    if (pThis->s.Core.cWriteRecursions == 1)
    702839    {
    703         AssertReturn(pThis->cWriterReads == 0, VERR_WRONG_ORDER); /* (must release all read recursions before the final write.) */
    704 #ifdef RTCRITSECTRW_STRICT
    705         int rc9 = RTLockValidatorRecExclReleaseOwner(pThis->pValidatorWrite, true);
     840        AssertReturn(pThis->s.Core.cWriterReads == 0, VERR_WRONG_ORDER); /* (must release all read recursions before the final write.) */
     841#ifdef PDMCRITSECTRW_STRICT
     842        int rc9 = RTLockValidatorRecExclReleaseOwner(pThis->s.Core.pValidatorWrite, true);
    706843        if (RT_FAILURE(rc9))
    707844            return rc9;
     
    710847         * Update the state.
    711848         */
    712         ASMAtomicWriteU32(&pThis->cWriteRecursions, 0);
    713         ASMAtomicWriteHandle(&pThis->hNativeWriter, NIL_RTNATIVETHREAD);
     849        ASMAtomicWriteU32(&pThis->s.Core.cWriteRecursions, 0);
     850        ASMAtomicWriteHandle(&pThis->s.Core.hNativeWriter, NIL_RTNATIVETHREAD);
    714851
    715852        for (;;)
    716853        {
    717             uint64_t u64State    = ASMAtomicReadU64(&pThis->u64State);
     854            uint64_t u64State    = ASMAtomicReadU64(&pThis->s.Core.u64State);
    718855            uint64_t u64OldState = u64State;
    719856
     
    728865                u64State &= ~RTCSRW_CNT_WR_MASK;
    729866                u64State |= c << RTCSRW_CNT_WR_SHIFT;
    730                 if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     867                if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    731868                {
    732869                    if (c > 0)
    733870                    {
    734                         int rc = RTSemEventSignal(pThis->hEvtWrite);
     871                        int rc = SUPSemEventSignal(pThis->s.CTX_SUFF(pVM)->pSession, (SUPSEMEVENT)pThis->s.Core.hEvtWrite);
    735872                        AssertRC(rc);
    736873                    }
     
    743880                u64State &= ~(RTCSRW_CNT_WR_MASK | RTCSRW_DIR_MASK);
    744881                u64State |= RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT;
    745                 if (ASMAtomicCmpXchgU64(&pThis->u64State, u64State, u64OldState))
     882                if (ASMAtomicCmpXchgU64(&pThis->s.Core.u64State, u64State, u64OldState))
    746883                {
    747                     Assert(!pThis->fNeedReset);
    748                     ASMAtomicWriteBool(&pThis->fNeedReset, true);
    749                     int rc = RTSemEventMultiSignal(pThis->hEvtRead);
     884                    Assert(!pThis->s.Core.fNeedReset);
     885                    ASMAtomicWriteBool(&pThis->s.Core.fNeedReset, true);
     886                    int rc = SUPSemEventMultiSignal(pThis->s.CTX_SUFF(pVM)->pSession, (SUPSEMEVENTMULTI)pThis->s.Core.hEvtRead);
    750887                    AssertRC(rc);
    751888                    break;
     
    754891
    755892            ASMNopPause();
    756             if (pThis->u32Magic != RTCRITSECTRW_MAGIC)
     893            if (pThis->s.Core.u32Magic != RTCRITSECTRW_MAGIC)
    757894                return VERR_SEM_DESTROYED;
    758895        }
     
    760897    else
    761898    {
    762         Assert(pThis->cWriteRecursions != 0);
    763 #ifdef RTCRITSECTRW_STRICT
    764         int rc9 = RTLockValidatorRecExclUnwind(pThis->pValidatorWrite);
     899        Assert(pThis->s.Core.cWriteRecursions != 0);
     900#ifdef PDMCRITSECTRW_STRICT
     901        int rc9 = RTLockValidatorRecExclUnwind(pThis->s.Core.pValidatorWrite);
    765902        if (RT_FAILURE(rc9))
    766903            return rc9;
    767904#endif
    768         ASMAtomicDecU32(&pThis->cWriteRecursions);
     905        ASMAtomicDecU32(&pThis->s.Core.cWriteRecursions);
    769906    }
    770907
    771908    return VINF_SUCCESS;
    772909}
    773 RT_EXPORT_SYMBOL(RTSemRWReleaseWrite);
    774 
    775 
    776 RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis)
     910
     911
     912/**
     913 * Checks the caller is the exclusive (write) owner of the critical section.
     914 *
     915 * @retval  @c true if owner.
     916 * @retval  @c false if not owner.
     917 * @param   pThis       Pointer to the read/write critical section.
     918 * @sa      PDMCritSectRwIsReadOwner, PDMCritSectIsOwner,
     919 *          RTCritSectRwIsWriteOwner.
     920 */
     921VMMDECL(bool) PDMCritSectRwIsWriteOwner(PPDMCRITSECTRW pThis)
    777922{
    778923    /*
     
    780925     */
    781926    AssertPtr(pThis);
    782     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, false);
     927    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, false);
    783928
    784929    /*
    785930     * Check ownership.
    786931     */
    787     RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
    788932    RTNATIVETHREAD hNativeWriter;
    789     ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hNativeWriter);
    790     return hNativeWriter == hNativeSelf;
    791 }
    792 RT_EXPORT_SYMBOL(RTCritSectRwIsWriteOwner);
    793 
    794 
    795 RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear)
     933    ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hNativeWriter);
     934    if (hNativeWriter == NIL_RTNATIVETHREAD)
     935        return false;
     936    return hNativeWriter == pdmCritSectRwGetNativeSelf(pThis);
     937}
     938
     939
     940/**
     941 * Checks if the caller is one of the read owners of the critical section.
     942 *
     943 * @note    !CAUTION!  This API doesn't work reliably if lock validation isn't
     944 *          enabled. Meaning, the answer is not trustworhty unless
     945 *          RT_LOCK_STRICT or PDMCRITSECTRW_STRICT was defined at build time.
     946 *          Also, make sure you do not use RTCRITSECTRW_FLAGS_NO_LOCK_VAL when
     947 *          creating the semaphore.  And finally, if you used a locking class,
     948 *          don't disable deadlock detection by setting cMsMinDeadlock to
     949 *          RT_INDEFINITE_WAIT.
     950 *
     951 *          In short, only use this for assertions.
     952 *
     953 * @returns @c true if reader, @c false if not.
     954 * @param   pThis       Pointer to the read/write critical section.
     955 * @param   fWannaHear  What you'd like to hear when lock validation is not
     956 *                      available.  (For avoiding asserting all over the place.)
     957 * @sa      PDMCritSectRwIsWriteOwner, RTCritSectRwIsReadOwner.
     958 */
     959VMMDECL(bool) PDMCritSectRwIsReadOwner(PPDMCRITSECTRW pThis, bool fWannaHear)
    796960{
    797961    /*
     
    799963     */
    800964    AssertPtr(pThis);
    801     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, false);
     965    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, false);
    802966
    803967    /*
    804968     * Inspect the state.
    805969     */
    806     uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
     970    uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    807971    if ((u64State & RTCSRW_DIR_MASK) == (RTCSRW_DIR_WRITE << RTCSRW_DIR_SHIFT))
    808972    {
     
    811975         * current writer.
    812976         */
    813         RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
    814977        RTNATIVETHREAD hWriter;
    815         ASMAtomicUoReadHandle(&pThis->hNativeWriter, &hWriter);
    816         return hWriter == hNativeSelf;
     978        ASMAtomicUoReadHandle(&pThis->s.Core.hNativeWriter, &hWriter);
     979        if (hWriter == NIL_RTNATIVETHREAD)
     980            return false;
     981        return hWriter == pdmCritSectRwGetNativeSelf(pThis);
    817982    }
    818983
     
    823988        return false;
    824989
    825 #ifdef RTCRITSECTRW_STRICT
     990#if defined(PDMCRITSECTRW_STRICT) && defined(IN_RING3)
    826991    /*
    827992     * Ask the lock validator.
    828      */
    829     return RTLockValidatorRecSharedIsOwner(pThis->pValidatorRead, NIL_RTTHREAD);
     993     * Note! It doesn't know everything, let's deal with that if it becomes an issue...
     994     */
     995    return RTLockValidatorRecSharedIsOwner(pThis->s.Core.pValidatorRead, NIL_RTTHREAD);
    830996#else
    831997    /*
     
    8351001#endif
    8361002}
    837 RT_EXPORT_SYMBOL(RTCritSectRwIsReadOwner);
    838 
    839 
    840 RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis)
     1003
     1004
     1005/**
     1006 * Gets the write recursion count.
     1007 *
     1008 * @returns The write recursion count (0 if bad critsect).
     1009 * @param   pThis       Pointer to the read/write critical section.
     1010 * @sa      PDMCritSectRwGetWriterReadRecursion, PDMCritSectRwGetReadCount,
     1011 *          RTCritSectRwGetWriteRecursion.
     1012 */
     1013VMMDECL(uint32_t) PDMCritSectRwGetWriteRecursion(PPDMCRITSECTRW pThis)
    8411014{
    8421015    /*
     
    8441017     */
    8451018    AssertPtr(pThis);
    846     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, 0);
     1019    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, 0);
    8471020
    8481021    /*
    8491022     * Return the requested data.
    8501023     */
    851     return pThis->cWriteRecursions;
    852 }
    853 RT_EXPORT_SYMBOL(RTCritSectRwGetWriteRecursion);
    854 
    855 
    856 RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis)
     1024    return pThis->s.Core.cWriteRecursions;
     1025}
     1026
     1027
     1028/**
     1029 * Gets the read recursion count of the current writer.
     1030 *
     1031 * @returns The read recursion count (0 if bad critsect).
     1032 * @param   pThis       Pointer to the read/write critical section.
     1033 * @sa      PDMCritSectRwGetWriteRecursion, PDMCritSectRwGetReadCount,
     1034 *          RTCritSectRwGetWriterReadRecursion.
     1035 */
     1036VMMDECL(uint32_t) PDMCritSectRwGetWriterReadRecursion(PPDMCRITSECTRW pThis)
    8571037{
    8581038    /*
     
    8601040     */
    8611041    AssertPtr(pThis);
    862     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, 0);
     1042    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, 0);
    8631043
    8641044    /*
    8651045     * Return the requested data.
    8661046     */
    867     return pThis->cWriterReads;
    868 }
    869 RT_EXPORT_SYMBOL(RTSemRWGetWriterReadRecursion);
    870 
    871 
    872 RTDECL(uint32_t) RTSemRWGetReadCount(PRTCRITSECTRW pThis)
     1047    return pThis->s.Core.cWriterReads;
     1048}
     1049
     1050
     1051/**
     1052 * Gets the current number of reads.
     1053 *
     1054 * This includes all read recursions, so it might be higher than the number of
     1055 * read owners.  It does not include reads done by the current writer.
     1056 *
     1057 * @returns The read count (0 if bad critsect).
     1058 * @param   pThis       Pointer to the read/write critical section.
     1059 * @sa      PDMCritSectRwGetWriteRecursion, PDMCritSectRwGetWriterReadRecursion,
     1060 *          RTCritSectRwGetReadCount.
     1061 */
     1062VMMDECL(uint32_t) PDMCritSectRwGetReadCount(PPDMCRITSECTRW pThis)
    8731063{
    8741064    /*
     
    8761066     */
    8771067    AssertPtr(pThis);
    878     AssertReturn(pThis->u32Magic == RTCRITSECTRW_MAGIC, 0);
     1068    AssertReturn(pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC, 0);
    8791069
    8801070    /*
    8811071     * Return the requested data.
    8821072     */
    883     uint64_t u64State = ASMAtomicReadU64(&pThis->u64State);
     1073    uint64_t u64State = ASMAtomicReadU64(&pThis->s.Core.u64State);
    8841074    if ((u64State & RTCSRW_DIR_MASK) != (RTCSRW_DIR_READ << RTCSRW_DIR_SHIFT))
    8851075        return 0;
    8861076    return (u64State & RTCSRW_CNT_RD_MASK) >> RTCSRW_CNT_RD_SHIFT;
    8871077}
    888 RT_EXPORT_SYMBOL(RTSemRWGetReadCount);
    889 
    890 
    891 RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis)
    892 {
    893     /*
    894      * Assert free waiters and so on.
    895      */
     1078
     1079
     1080/**
     1081 * Checks if the read/write critical section is initialized or not.
     1082 *
     1083 * @retval  @c true if initialized.
     1084 * @retval  @c false if not initialized.
     1085 * @param   pThis       Pointer to the read/write critical section.
     1086 * @sa      PDMCritSectIsInitialized, RTCritSectRwIsInitialized.
     1087 */
     1088VMMDECL(bool) PDMCritSectRwIsInitialized(PCPDMCRITSECTRW pThis)
     1089{
    8961090    AssertPtr(pThis);
    897     Assert(pThis->u32Magic == RTCRITSECTRW_MAGIC);
    898     //Assert(pThis->cNestings == 0);
    899     //Assert(pThis->cLockers == -1);
    900     Assert(pThis->hNativeWriter == NIL_RTNATIVETHREAD);
    901 
    902     /*
    903      * Invalidate the structure and free the semaphores.
    904      */
    905     if (!ASMAtomicCmpXchgU32(&pThis->u32Magic, RTCRITSECTRW_MAGIC_DEAD, RTCRITSECTRW_MAGIC))
    906         return VERR_INVALID_PARAMETER;
    907 
    908     pThis->fFlags   = 0;
    909     pThis->u64State = 0;
    910 
    911     RTSEMEVENT      hEvtWrite = pThis->hEvtWrite;
    912     pThis->hEvtWrite = NIL_RTSEMEVENT;
    913     RTSEMEVENTMULTI hEvtRead  = pThis->hEvtRead;
    914     pThis->hEvtRead  = NIL_RTSEMEVENTMULTI;
    915 
    916     int rc1 = RTSemEventDestroy(hEvtWrite);     AssertRC(rc1);
    917     int rc2 = RTSemEventMultiDestroy(hEvtRead); AssertRC(rc2);
    918 
    919     RTLockValidatorRecSharedDestroy(&pThis->pValidatorRead);
    920     RTLockValidatorRecExclDestroy(&pThis->pValidatorWrite);
    921 
    922     return RT_SUCCESS(rc1) ? rc2 : rc1;
    923 }
    924 RT_EXPORT_SYMBOL(RTCritSectRwDelete);
    925 
     1091    return pThis->s.Core.u32Magic == RTCRITSECTRW_MAGIC;
     1092}
     1093
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r45108 r45152  
    14091409
    14101410    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PDM_CRITSECT))
    1411         PDMCritSectFF(pVCpu);
     1411        PDMCritSectBothFF(pVCpu);
    14121412
    14131413    /* Update CR3 (Nested Paging case for HM). */
  • trunk/src/VBox/VMM/VMMR3/PDM.cpp

    r45024 r45152  
    343343    pUVM->pdm.s.pModules   = NULL;
    344344    pUVM->pdm.s.pCritSects = NULL;
     345    pUVM->pdm.s.pRwCritSects = NULL;
    345346    return RTCritSectInit(&pUVM->pdm.s.ListCritSect);
    346347}
     
    374375     * Initialize critical sections first.
    375376     */
    376     int rc = pdmR3CritSectInitStats(pVM);
     377    int rc = pdmR3CritSectBothInitStats(pVM);
    377378    if (RT_SUCCESS(rc))
    378379        rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.CritSect, RT_SRC_POS, "PDM");
     
    458459     * Critical sections.
    459460     */
    460     pdmR3CritSectRelocate(pVM);
     461    pdmR3CritSectBothRelocate(pVM);
    461462
    462463    /*
     
    660661        TMR3TimerDestroyDevice(pVM, pDevIns);
    661662        SSMR3DeregisterDevice(pVM, pDevIns, NULL, 0);
    662         pdmR3CritSectDeleteDevice(pVM, pDevIns);
     663        pdmR3CritSectBothDeleteDevice(pVM, pDevIns);
    663664        pdmR3ThreadDestroyDevice(pVM, pDevIns);
    664665        PDMR3QueueDestroyDevice(pVM, pDevIns);
     
    702703     */
    703704    PDMR3CritSectDelete(&pVM->pdm.s.CritSect);
    704     /* The MiscCritSect is deleted by PDMR3CritSectTerm. */
     705    /* The MiscCritSect is deleted by PDMR3CritSectBothTerm later. */
    705706
    706707    LogFlow(("PDMR3Term: returns %Rrc\n", VINF_SUCCESS));
     
    726727
    727728    Assert(pUVM->pdm.s.pCritSects == NULL);
     729    Assert(pUVM->pdm.s.pRwCritSects == NULL);
    728730    RTCritSectDelete(&pUVM->pdm.s.ListCritSect);
    729731}
  • trunk/src/VBox/VMM/VMMR3/PDMCritSect.cpp

    r44528 r45152  
    2323#include "PDMInternal.h"
    2424#include <VBox/vmm/pdmcritsect.h>
     25#include <VBox/vmm/pdmcritsectrw.h>
    2526#include <VBox/vmm/mm.h>
    2627#include <VBox/vmm/vm.h>
     
    4142*******************************************************************************/
    4243static int pdmR3CritSectDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal);
     44static int pdmR3CritSectRwDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTRWINT pCritSect, PPDMCRITSECTRWINT pPrev, bool fFinal);
    4345
    4446
     
    5052 * @param   pVM         Pointer to the VM.
    5153 */
    52 int pdmR3CritSectInitStats(PVM pVM)
     54int pdmR3CritSectBothInitStats(PVM pVM)
    5355{
    5456    STAM_REG(pVM, &pVM->pdm.s.StatQueuedCritSectLeaves, STAMTYPE_COUNTER, "/PDM/QueuedCritSectLeaves", STAMUNIT_OCCURENCES,
     
    6365 * @param   pVM         Pointer to the VM.
    6466 */
    65 void pdmR3CritSectRelocate(PVM pVM)
     67void pdmR3CritSectBothRelocate(PVM pVM)
    6668{
    6769    PUVM pUVM = pVM->pUVM;
     
    6971
    7072    for (PPDMCRITSECTINT pCur = pUVM->pdm.s.pCritSects;
     73         pCur;
     74         pCur = pCur->pNext)
     75        pCur->pVMRC = pVM->pVMRC;
     76
     77    for (PPDMCRITSECTRWINT pCur = pUVM->pdm.s.pRwCritSects;
    7178         pCur;
    7279         pCur = pCur->pNext)
     
    9198 * @remark  Don't confuse this with PDMR3CritSectDelete.
    9299 */
    93 VMMDECL(int) PDMR3CritSectTerm(PVM pVM)
     100VMMR3_INT_DECL(int) PDMR3CritSectBothTerm(PVM pVM)
    94101{
    95102    PUVM    pUVM = pVM->pUVM;
     
    100107    {
    101108        int rc2 = pdmR3CritSectDeleteOne(pVM, pUVM, pUVM->pdm.s.pCritSects, NULL, true /* final */);
     109        AssertRC(rc2);
     110        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     111            rc = rc2;
     112    }
     113
     114    while (pUVM->pdm.s.pRwCritSects)
     115    {
     116        int rc2 = pdmR3CritSectRwDeleteOne(pVM, pUVM, pUVM->pdm.s.pRwCritSects, NULL, true /* final */);
    102117        AssertRC(rc2);
    103118        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     
    127142{
    128143    VM_ASSERT_EMT(pVM);
     144    Assert(pCritSect->Core.u32Magic != RTCRITSECT_MAGIC);
    129145
    130146    /*
     
    168184                pCritSect->fUsedByTimerOrSimilar     = false;
    169185                pCritSect->EventToSignal             = NIL_RTSEMEVENT;
    170                 pCritSect->pNext                     = pVM->pUVM->pdm.s.pCritSects;
    171186                pCritSect->pszName                   = pszName;
    172                 pVM->pUVM->pdm.s.pCritSects = pCritSect;
     187
    173188                STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLock,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZLock", pCritSect->pszName);
    174189                STAMR3RegisterF(pVM, &pCritSect->StatContentionRZUnlock,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZUnlock", pCritSect->pszName);
     
    177192                STAMR3RegisterF(pVM, &pCritSect->StatLocked,        STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSects/%s/Locked", pCritSect->pszName);
    178193#endif
     194
     195                PUVM pUVM = pVM->pUVM;
     196                RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     197                pCritSect->pNext = pUVM->pdm.s.pCritSects;
     198                pUVM->pdm.s.pCritSects = pCritSect;
     199                RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     200
    179201                return VINF_SUCCESS;
    180202            }
     
    191213
    192214/**
     215 * Initializes a read/write critical section and inserts it into the list.
     216 *
     217 * @returns VBox status code.
     218 * @param   pVM             Pointer to the VM.
     219 * @param   pCritSect       The read/write critical section.
     220 * @param   pvKey           The owner key.
     221 * @param   RT_SRC_POS_DECL The source position.
     222 * @param   pszName         The name of the critical section (for statistics).
     223 * @param   pszNameFmt      Format string for naming the critical section.  For
     224 *                          statistics and lock validation.
     225 * @param   va              Arguments for the format string.
     226 */
     227static int pdmR3CritSectRwInitOne(PVM pVM, PPDMCRITSECTRWINT pCritSect, void *pvKey, RT_SRC_POS_DECL,
     228                                  const char *pszNameFmt, va_list va)
     229{
     230    VM_ASSERT_EMT(pVM);
     231    Assert(pCritSect->Core.u32Magic != RTCRITSECTRW_MAGIC);
     232
     233    /*
     234     * Allocate the semaphores.
     235     */
     236    AssertCompile(sizeof(SUPSEMEVENT) == sizeof(pCritSect->Core.hEvtWrite));
     237    int rc = SUPSemEventCreate(pVM->pSession, (PSUPSEMEVENT)&pCritSect->Core.hEvtWrite);
     238    if (RT_SUCCESS(rc))
     239    {
     240        AssertCompile(sizeof(SUPSEMEVENTMULTI) == sizeof(pCritSect->Core.hEvtRead));
     241        rc = SUPSemEventMultiCreate(pVM->pSession, (PSUPSEMEVENT)&pCritSect->Core.hEvtRead);
     242        if (RT_SUCCESS(rc))
     243        {
     244            /* Only format the name once. */
     245            char *pszName = RTStrAPrintf2V(pszNameFmt, va); /** @todo plug the "leak"... */
     246            if (pszName)
     247            {
     248                pCritSect->Core.pValidatorRead  = NULL;
     249                pCritSect->Core.pValidatorWrite = NULL;
     250#ifdef PDMCRITSECT_STRICT
     251# ifdef RT_LOCK_STRICT_ORDER
     252                RTLOCKVALCLASS hClass = RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, "%s", pszName);
     253# else
     254                RTLOCKVALCLASS hClass = NIL_RTLOCKVALCLASS;
     255# endif
     256                rc = RTLockValidatorRecExclCreate(&pCritSect->Core.pValidatorWrite, hClass, RTLOCKVAL_SUB_CLASS_NONE,
     257                                                  pCritSect, true, "%s", pszName);
     258                if (RT_SUCCESS(rc))
     259                    rc = RTLockValidatorRecSharedCreate(&pCritSect->Core.pValidatorRead, hClass, RTLOCKVAL_SUB_CLASS_NONE,
     260                                                        pCritSect, false /*fSignaller*/, true, "%s", pszName);
     261#endif
     262                if (RT_SUCCESS(rc))
     263                {
     264                    /*
     265                     * Initialize the structure (first bit is c&p from RTCritSectRwInitEx).
     266                     */
     267                    pCritSect->Core.u32Magic             = RTCRITSECTRW_MAGIC_DEAD;
     268                    pCritSect->Core.fNeedReset           = false;
     269                    pCritSect->Core.u64State             = 0;
     270                    pCritSect->Core.hNativeWriter        = NIL_RTNATIVETHREAD;
     271                    pCritSect->Core.cWriterReads         = 0;
     272                    pCritSect->Core.cWriteRecursions     = 0;
     273                    pCritSect->Core.pValidatorWrite      = NULL;
     274                    pCritSect->Core.pValidatorRead       = NULL;
     275#if HC_ARCH_BITS == 32
     276                    pCritSect->Core.HCPtrPadding         = NIL_RTHCPTR;
     277#endif
     278                    pCritSect->pVMR3                     = pVM;
     279                    pCritSect->pVMR0                     = pVM->pVMR0;
     280                    pCritSect->pVMRC                     = pVM->pVMRC;
     281                    pCritSect->pvKey                     = pvKey;
     282                    pCritSect->pszName                   = pszName;
     283
     284                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZEnterExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZEnterExcl", pCritSect->pszName);
     285                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLeaveExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZLeaveExcl", pCritSect->pszName);
     286                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZEnterShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZEnterShared", pCritSect->pszName);
     287                    STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLeaveShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionRZLeaveShared", pCritSect->pszName);
     288                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3EnterExcl,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3EnterExcl", pCritSect->pszName);
     289                    STAMR3RegisterF(pVM, &pCritSect->StatContentionR3EnterShared, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/ContentionR3EnterShared", pCritSect->pszName);
     290                    STAMR3RegisterF(pVM, &pCritSect->StatRZEnterExcl,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/RZEnterExcl", pCritSect->pszName);
     291                    STAMR3RegisterF(pVM, &pCritSect->StatRZEnterShared,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/RZEnterShared", pCritSect->pszName);
     292                    STAMR3RegisterF(pVM, &pCritSect->StatR3EnterExcl,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/R3EnterExcl", pCritSect->pszName);
     293                    STAMR3RegisterF(pVM, &pCritSect->StatR3EnterShared,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSectsRw/%s/R3EnterShared", pCritSect->pszName);
     294#ifdef VBOX_WITH_STATISTICS
     295                    STAMR3RegisterF(pVM, &pCritSect->StatWriteLocked,         STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSectsRw/%s/WriteLocked", pCritSect->pszName);
     296#endif
     297
     298                    PUVM pUVM = pVM->pUVM;
     299                    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     300                    pCritSect->pNext = pUVM->pdm.s.pRwCritSects;
     301                    pUVM->pdm.s.pRwCritSects = pCritSect;
     302                    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     303
     304                    return VINF_SUCCESS;
     305                }
     306
     307                RTStrFree(pszName);
     308            }
     309            else
     310                rc = VERR_NO_STR_MEMORY;
     311            SUPSemEventMultiClose(pVM->pSession, (SUPSEMEVENT)pCritSect->Core.hEvtRead);
     312        }
     313        SUPSemEventClose(pVM->pSession, (SUPSEMEVENT)pCritSect->Core.hEvtWrite);
     314    }
     315    return rc;
     316}
     317
     318
     319/**
    193320 * Initializes a PDM critical section for internal use.
    194321 *
    195322 * The PDM critical sections are derived from the IPRT critical sections, but
    196  * works in GC as well.
     323 * works in ring-0 and raw-mode context as well.
    197324 *
    198325 * @returns VBox status code.
     
    204331 *                          statistics and lock validation.
    205332 * @param   ...             Arguments for the format string.
    206  * @thread  EMT(0)
     333 * @thread  EMT
    207334 */
    208335VMMR3DECL(int) PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...)
     
    221348
    222349/**
     350 * Initializes a PDM read/write critical section for internal use.
     351 *
     352 * The PDM read/write critical sections are derived from the IPRT read/write
     353 * critical sections, but works in ring-0 and raw-mode context as well.
     354 *
     355 * @returns VBox status code.
     356 * @param   pVM             Pointer to the VM.
     357 * @param   pDevIns         Device instance.
     358 * @param   pCritSect       Pointer to the read/write critical section.
     359 * @param   RT_SRC_POS_DECL Use RT_SRC_POS.
     360 * @param   pszNameFmt      Format string for naming the critical section.  For
     361 *                          statistics and lock validation.
     362 * @param   ...             Arguments for the format string.
     363 * @thread  EMT
     364 */
     365VMMR3DECL(int) PDMR3CritSectRwInit(PVM pVM, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...)
     366{
     367#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
     368    AssertCompile(sizeof(pCritSect->padding) >= sizeof(pCritSect->s));
     369#endif
     370    Assert(RT_ALIGN_P(pCritSect, sizeof(uintptr_t)) == pCritSect);
     371    va_list va;
     372    va_start(va, pszNameFmt);
     373    int rc = pdmR3CritSectRwInitOne(pVM, &pCritSect->s, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
     374    va_end(va);
     375    return rc;
     376}
     377
     378
     379/**
    223380 * Initializes a PDM critical section for a device.
    224  *
    225  * The PDM critical sections are derived from the IPRT critical sections, but
    226  * works in GC as well.
    227381 *
    228382 * @returns VBox status code.
     
    238392{
    239393    return pdmR3CritSectInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
     394}
     395
     396
     397/**
     398 * Initializes a PDM read/write critical section for a device.
     399 *
     400 * @returns VBox status code.
     401 * @param   pVM             Pointer to the VM.
     402 * @param   pDevIns         Device instance.
     403 * @param   pCritSect       Pointer to the read/write critical section.
     404 * @param   pszNameFmt      Format string for naming the critical section.  For
     405 *                          statistics and lock validation.
     406 * @param   va              Arguments for the format string.
     407 */
     408int pdmR3CritSectRwInitDevice(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     409                              const char *pszNameFmt, va_list va)
     410{
     411    return pdmR3CritSectRwInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
    240412}
    241413
     
    279451    va_start(va, pszNameFmt);
    280452    int rc = pdmR3CritSectInitOne(pVM, &pCritSect->s, pDrvIns, RT_SRC_POS_ARGS, pszNameFmt, va);
     453    va_end(va);
     454    return rc;
     455}
     456
     457
     458/**
     459 * Initializes a PDM read/write critical section for a driver.
     460 *
     461 * @returns VBox status code.
     462 * @param   pVM             Pointer to the VM.
     463 * @param   pDrvIns         Driver instance.
     464 * @param   pCritSect       Pointer to the read/write critical section.
     465 * @param   pszNameFmt      Format string for naming the critical section.  For
     466 *                          statistics and lock validation.
     467 * @param   ...             Arguments for the format string.
     468 */
     469int pdmR3CritSectRwInitDriver(PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     470                              const char *pszNameFmt, ...)
     471{
     472    va_list va;
     473    va_start(va, pszNameFmt);
     474    int rc = pdmR3CritSectRwInitOne(pVM, &pCritSect->s, pDrvIns, RT_SRC_POS_ARGS, pszNameFmt, va);
    281475    va_end(va);
    282476    return rc;
     
    349543
    350544/**
     545 * Deletes one read/write critical section.
     546 *
     547 * @returns VBox status code.
     548 *
     549 * @param   pVM         Pointer to the VM.
     550 * @param   pCritSect   The read/write critical section.
     551 * @param   pPrev       The previous critical section in the list.
     552 * @param   fFinal      Set if this is the final call and statistics shouldn't be deregistered.
     553 *
     554 * @remarks Caller must have entered the ListCritSect.
     555 */
     556static int pdmR3CritSectRwDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTRWINT pCritSect, PPDMCRITSECTRWINT pPrev, bool fFinal)
     557{
     558    /*
     559     * Assert free waiters and so on (c&p from RTCritSectRwDelete).
     560     */
     561    Assert(pCritSect->Core.u32Magic == RTCRITSECTRW_MAGIC);
     562    //Assert(pCritSect->Core.cNestings == 0);
     563    //Assert(pCritSect->Core.cLockers == -1);
     564    Assert(pCritSect->Core.hNativeWriter == NIL_RTNATIVETHREAD);
     565
     566    /*
     567     * Invalidate the structure and free the semaphores.
     568     */
     569    if (!ASMAtomicCmpXchgU32(&pCritSect->Core.u32Magic, RTCRITSECTRW_MAGIC_DEAD, RTCRITSECTRW_MAGIC))
     570        AssertFailed();
     571
     572    /*
     573     * Unlink it.
     574     */
     575    if (pPrev)
     576        pPrev->pNext = pCritSect->pNext;
     577    else
     578        pUVM->pdm.s.pRwCritSects = pCritSect->pNext;
     579
     580    /*
     581     * Delete it (parts taken from RTCritSectRwDelete).
     582     * In case someone is waiting we'll signal the semaphore cLockers + 1 times.
     583     */
     584    pCritSect->Core.fFlags   = 0;
     585    pCritSect->Core.u64State = 0;
     586
     587    SUPSEMEVENT      hEvtWrite = (SUPSEMEVENT)pCritSect->Core.hEvtWrite;
     588    pCritSect->Core.hEvtWrite  = NIL_RTSEMEVENT;
     589    AssertCompile(sizeof(hEvtWrite) == sizeof(pCritSect->Core.hEvtWrite));
     590
     591    SUPSEMEVENTMULTI hEvtRead  = (SUPSEMEVENTMULTI)pCritSect->Core.hEvtRead;
     592    pCritSect->Core.hEvtRead   = NIL_RTSEMEVENTMULTI;
     593    AssertCompile(sizeof(hEvtRead) == sizeof(pCritSect->Core.hEvtRead));
     594
     595    int rc1 = SUPSemEventClose(pVM->pSession, hEvtWrite);     AssertRC(rc1);
     596    int rc2 = SUPSemEventMultiClose(pVM->pSession, hEvtRead); AssertRC(rc2);
     597
     598    RTLockValidatorRecSharedDestroy(&pCritSect->Core.pValidatorRead);
     599    RTLockValidatorRecExclDestroy(&pCritSect->Core.pValidatorWrite);
     600
     601    pCritSect->pNext   = NULL;
     602    pCritSect->pvKey   = NULL;
     603    pCritSect->pVMR3   = NULL;
     604    pCritSect->pVMR0   = NIL_RTR0PTR;
     605    pCritSect->pVMRC   = NIL_RTRCPTR;
     606    RTStrFree((char *)pCritSect->pszName);
     607    pCritSect->pszName = NULL;
     608    if (!fFinal)
     609    {
     610        STAMR3Deregister(pVM, &pCritSect->StatContentionRZEnterExcl);
     611        STAMR3Deregister(pVM, &pCritSect->StatContentionRZLeaveExcl);
     612        STAMR3Deregister(pVM, &pCritSect->StatContentionRZEnterShared);
     613        STAMR3Deregister(pVM, &pCritSect->StatContentionRZLeaveShared);
     614        STAMR3Deregister(pVM, &pCritSect->StatRZEnterExcl);
     615        STAMR3Deregister(pVM, &pCritSect->StatRZEnterShared);
     616        STAMR3Deregister(pVM, &pCritSect->StatContentionR3EnterExcl);
     617        STAMR3Deregister(pVM, &pCritSect->StatContentionR3EnterShared);
     618        STAMR3Deregister(pVM, &pCritSect->StatR3EnterExcl);
     619        STAMR3Deregister(pVM, &pCritSect->StatR3EnterShared);
     620#ifdef VBOX_WITH_STATISTICS
     621        STAMR3Deregister(pVM, &pCritSect->StatWriteLocked);
     622#endif
     623    }
     624
     625    return RT_SUCCESS(rc1) ? rc2 : rc1;
     626}
     627
     628
     629/**
    351630 * Deletes all critical sections with a give initializer key.
    352631 *
     
    388667
    389668/**
    390  * Deletes all undeleted critical sections initialized by a given device.
     669 * Deletes all read/write critical sections with a give initializer key.
     670 *
     671 * @returns VBox status code.
     672 *          The entire list is processed on failure, so we'll only
     673 *          return the first error code. This shouldn't be a problem
     674 *          since errors really shouldn't happen here.
     675 * @param   pVM     Pointer to the VM.
     676 * @param   pvKey   The initializer key.
     677 */
     678static int pdmR3CritSectRwDeleteByKey(PVM pVM, void *pvKey)
     679{
     680    /*
     681     * Iterate the list and match key.
     682     */
     683    PUVM                pUVM  = pVM->pUVM;
     684    int                 rc    = VINF_SUCCESS;
     685    PPDMCRITSECTRWINT   pPrev = NULL;
     686    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     687    PPDMCRITSECTRWINT   pCur  = pUVM->pdm.s.pRwCritSects;
     688    while (pCur)
     689    {
     690        if (pCur->pvKey == pvKey)
     691        {
     692            int rc2 = pdmR3CritSectRwDeleteOne(pVM, pUVM, pCur, pPrev, false /* not final */);
     693            AssertRC(rc2);
     694            if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     695                rc = rc2;
     696        }
     697
     698        /* next */
     699        pPrev = pCur;
     700        pCur = pCur->pNext;
     701    }
     702    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     703    return rc;
     704}
     705
     706
     707/**
     708 * Deletes all undeleted critical sections (both types) initialized by a given
     709 * device.
    391710 *
    392711 * @returns VBox status code.
     
    394713 * @param   pDevIns     The device handle.
    395714 */
    396 int pdmR3CritSectDeleteDevice(PVM pVM, PPDMDEVINS pDevIns)
    397 {
    398     return pdmR3CritSectDeleteByKey(pVM, pDevIns);
    399 }
    400 
    401 
    402 /**
    403  * Deletes all undeleted critical sections initialized by a given driver.
     715int pdmR3CritSectBothDeleteDevice(PVM pVM, PPDMDEVINS pDevIns)
     716{
     717    int rc1 = pdmR3CritSectDeleteByKey(pVM, pDevIns);
     718    int rc2 = pdmR3CritSectRwDeleteByKey(pVM, pDevIns);
     719    return RT_SUCCESS(rc1) ? rc2 : rc1;
     720}
     721
     722
     723/**
     724 * Deletes all undeleted critical sections (both types) initialized by a given
     725 * driver.
    404726 *
    405727 * @returns VBox status code.
     
    407729 * @param   pDrvIns     The driver handle.
    408730 */
    409 int pdmR3CritSectDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns)
    410 {
    411     return pdmR3CritSectDeleteByKey(pVM, pDrvIns);
     731int pdmR3CritSectBothDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns)
     732{
     733    int rc1 = pdmR3CritSectDeleteByKey(pVM, pDrvIns);
     734    int rc2 = pdmR3CritSectRwDeleteByKey(pVM, pDrvIns);
     735    return RT_SUCCESS(rc1) ? rc2 : rc1;
    412736}
    413737
     
    453777
    454778/**
     779 * Deletes the read/write critical section.
     780 *
     781 * @returns VBox status code.
     782 * @param   pCritSect           The PDM read/write critical section to destroy.
     783 */
     784VMMR3DECL(int) PDMR3CritSectRwDelete(PPDMCRITSECTRW pCritSect)
     785{
     786    if (!PDMCritSectRwIsInitialized(pCritSect))
     787        return VINF_SUCCESS;
     788
     789    /*
     790     * Find and unlink it.
     791     */
     792    PVM                 pVM   = pCritSect->s.pVMR3;
     793    PUVM                pUVM  = pVM->pUVM;
     794    AssertReleaseReturn(pVM, VERR_PDM_CRITSECT_IPE);
     795    PPDMCRITSECTRWINT   pPrev = NULL;
     796    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     797    PPDMCRITSECTRWINT   pCur  = pUVM->pdm.s.pRwCritSects;
     798    while (pCur)
     799    {
     800        if (pCur == &pCritSect->s)
     801        {
     802            int rc = pdmR3CritSectRwDeleteOne(pVM, pUVM, pCur, pPrev, false /* not final */);
     803            RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     804            return rc;
     805        }
     806
     807        /* next */
     808        pPrev = pCur;
     809        pCur = pCur->pNext;
     810    }
     811    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     812    AssertReleaseMsgFailed(("pCritSect=%p wasn't found!\n", pCritSect));
     813    return VERR_PDM_CRITSECT_NOT_FOUND;
     814}
     815
     816
     817/**
    455818 * Gets the name of the critical section.
    456819 *
     
    464827    AssertPtrReturn(pCritSect, NULL);
    465828    AssertReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, NULL);
     829    return pCritSect->s.pszName;
     830}
     831
     832
     833/**
     834 * Gets the name of the read/write critical section.
     835 *
     836 *
     837 * @returns Pointer to the critical section name (read only) on success,
     838 *          NULL on failure (invalid critical section).
     839 * @param   pCritSect           The read/write critical section.
     840 */
     841VMMR3DECL(const char *) PDMR3CritSectRwName(PCPDMCRITSECTRW pCritSect)
     842{
     843    AssertPtrReturn(pCritSect, NULL);
     844    AssertReturn(pCritSect->s.Core.u32Magic == RTCRITSECTRW_MAGIC, NULL);
    466845    return pCritSect->s.pszName;
    467846}
     
    557936
    558937/**
    559  * Counts the critical sections owned by the calling thread, optionally
    560  * returning a comma separated list naming them.
     938 * PDMR3CritSectBothCountOwned worker.
     939 *
     940 * @param   pszName         The critical section name.
     941 * @param   ppszNames       Pointer to the pszNames variable.
     942 * @param   pcchLeft        Pointer to the cchLeft variable.
     943 * @param   fFirst          Whether this is the first name or not.
     944 */
     945static void pdmR3CritSectAppendNameToList(char const *pszName, char **ppszNames, size_t *pcchLeft, bool fFirst)
     946{
     947    size_t cchLeft = *pcchLeft;
     948    if (cchLeft)
     949    {
     950        char *pszNames = *ppszNames;
     951
     952        /* try add comma. */
     953        if (fFirst)
     954        {
     955            *pszNames++ = ',';
     956            if (--cchLeft)
     957            {
     958                *pszNames++ = ' ';
     959                cchLeft--;
     960            }
     961        }
     962
     963        /* try copy the name. */
     964        if (cchLeft)
     965        {
     966            size_t const cchName = strlen(pszName);
     967            if (cchName < cchLeft)
     968            {
     969                memcpy(pszNames, pszName, cchName);
     970                pszNames += cchName;
     971                cchLeft -= cchName;
     972            }
     973            else
     974            {
     975                if (cchLeft > 2)
     976                {
     977                    memcpy(pszNames, pszName, cchLeft - 2);
     978                    pszNames += cchLeft - 2;
     979                    cchLeft = 2;
     980                }
     981                while (cchLeft-- > 0)
     982                    *pszNames++ = '+';
     983            }
     984        }
     985        *pszNames = '\0';
     986
     987        *pcchLeft  = cchLeft;
     988        *ppszNames = pszNames;
     989    }
     990}
     991
     992
     993/**
     994 * Counts the critical sections (both type) owned by the calling thread,
     995 * optionally returning a comma separated list naming them.
     996 *
     997 * Read ownerships are not included in non-strict builds.
    561998 *
    562999 * This is for diagnostic purposes only.
     
    5831020     * Iterate the critical sections.
    5841021     */
     1022    uint32_t                cCritSects = 0;
     1023    RTNATIVETHREAD const    hNativeThread = RTThreadNativeSelf();
    5851024    /* This is unsafe, but wtf. */
    586     RTNATIVETHREAD const    hNativeThread = RTThreadNativeSelf();
    587     uint32_t                cCritSects = 0;
    5881025    for (PPDMCRITSECTINT pCur = pVM->pUVM->pdm.s.pCritSects;
    5891026         pCur;
     
    5941031        {
    5951032            cCritSects++;
    596 
    597             /*
    598              * Copy the name if there is space. Fun stuff.
    599              */
    600             if (cchLeft)
    601             {
    602                 /* try add comma. */
    603                 if (cCritSects != 1)
    604                 {
    605                     *pszNames++ = ',';
    606                     if (--cchLeft)
    607                     {
    608                         *pszNames++ = ' ';
    609                         cchLeft--;
    610                     }
    611                 }
    612 
    613                 /* try copy the name. */
    614                 if (cchLeft)
    615                 {
    616                     size_t const cchName = strlen(pCur->pszName);
    617                     if (cchName < cchLeft)
    618                     {
    619                         memcpy(pszNames, pCur->pszName, cchName);
    620                         pszNames += cchName;
    621                         cchLeft -= cchName;
    622                     }
    623                     else
    624                     {
    625                         if (cchLeft > 2)
    626                         {
    627                             memcpy(pszNames, pCur->pszName, cchLeft - 2);
    628                             pszNames += cchLeft - 2;
    629                             cchLeft = 2;
    630                         }
    631                         while (cchLeft-- > 0)
    632                             *pszNames++ = '+';
    633                     }
    634                 }
    635                 *pszNames = '\0';
    636             }
     1033            pdmR3CritSectAppendNameToList(pCur->pszName, &pszNames, &cchLeft, cCritSects == 1);
     1034        }
     1035    }
     1036
     1037    /* This is unsafe, but wtf. */
     1038    for (PPDMCRITSECTRWINT pCur = pVM->pUVM->pdm.s.pRwCritSects;
     1039         pCur;
     1040         pCur = pCur->pNext)
     1041    {
     1042        if (   pCur->Core.hNativeWriter == hNativeThread
     1043            || PDMCritSectRwIsReadOwner((PPDMCRITSECTRW)pCur, false /*fWannaHear*/) )
     1044        {
     1045            cCritSects++;
     1046            pdmR3CritSectAppendNameToList(pCur->pszName, &pszNames, &cchLeft, cCritSects == 1);
    6371047        }
    6381048    }
     
    6501060 * @param   pVM         Pointer to the VM.
    6511061 */
    652 VMMR3DECL(void) PDMR3CritSectLeaveAll(PVM pVM)
     1062VMMR3_INT_DECL(void) PDMR3CritSectLeaveAll(PVM pVM)
    6531063{
    6541064    RTNATIVETHREAD const hNativeSelf = RTThreadNativeSelf();
  • trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp

    r44358 r45152  
    962962
    963963        /* PDM critsects. */
    964         rc = pdmR3CritSectDeleteDriver(pVM, pCur);
     964        rc = pdmR3CritSectBothDeleteDriver(pVM, pCur);
    965965        AssertRC(rc);
    966966
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r45024 r45152  
    781781         * references to it are still working.
    782782         */
    783         PDMR3CritSectTerm(pVM);
     783        PDMR3CritSectBothTerm(pVM);
    784784
    785785        /*
     
    24402440        AssertRC(rc);
    24412441        SSMR3Term(pVM);
    2442         rc = PDMR3CritSectTerm(pVM);
     2442        rc = PDMR3CritSectBothTerm(pVM);
    24432443        AssertRC(rc);
    24442444        rc = MMR3Term(pVM);
  • trunk/src/VBox/VMM/VMMR3/VMM.cpp

    r44971 r45152  
    20982098     */
    20992099    if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PDM_CRITSECT))
    2100         PDMCritSectFF(pVCpu);
     2100        PDMCritSectBothFF(pVCpu);
    21012101
    21022102    switch (pVCpu->vmm.s.enmCallRing3Operation)
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r44528 r45152  
    3333#include <VBox/vmm/pdmblkcache.h>
    3434#include <VBox/vmm/pdmcommon.h>
     35#include <VBox/sup.h>
    3536#include <iprt/assert.h>
    3637#include <iprt/critsect.h>
     
    5657/** @def PDMCRITSECT_STRICT
    5758 * Enables/disables PDM critsect strictness like deadlock detection. */
    58 #if (defined(RT_LOCK_STRICT) && defined(IN_RING3) && !defined(IEM_VERIFICATION_MODE)) || defined(DOXYGEN_RUNNING)
     59#if (defined(RT_LOCK_STRICT) && defined(IN_RING3) && !defined(IEM_VERIFICATION_MODE) && !defined(PDMCRITSECT_STRICT)) \
     60  || defined(DOXYGEN_RUNNING)
    5961# define PDMCRITSECT_STRICT
     62#endif
     63
     64/** @def PDMCRITSECT_STRICT
     65 * Enables/disables PDM read/write critsect strictness like deadlock
     66 * detection. */
     67#if (defined(RT_LOCK_STRICT) && defined(IN_RING3) && !defined(IEM_VERIFICATION_MODE) && !defined(PDMCRITSECTRW_STRICT)) \
     68  || defined(DOXYGEN_RUNNING)
     69# define PDMCRITSECTRW_STRICT
    6070#endif
    6171
     
    263273typedef struct PDMCRITSECTINT
    264274{
    265     /** The critical section core which is shared with IPRT. */
     275    /** The critical section core which is shared with IPRT.
     276     * @note The semaphore is a SUPSEMEVENT.  */
    266277    RTCRITSECT                      Core;
    267278    /** Pointer to the next critical section.
     
    310321
    311322/**
     323 * Private critical section data.
     324 */
     325typedef struct PDMCRITSECTRWINT
     326{
     327    /** The read/write critical section core which is shared with IPRT.
     328     * @note The semaphores are SUPSEMEVENT and SUPSEMEVENTMULTI.  */
     329    RTCRITSECTRW                        Core;
     330
     331    /** Pointer to the next critical section.
     332     * This chain is used for relocating pVMRC and device cleanup. */
     333    R3PTRTYPE(struct PDMCRITSECTRWINT *) pNext;
     334    /** Owner identifier.
     335     * This is pDevIns if the owner is a device. Similarly for a driver or service.
     336     * PDMR3CritSectInit() sets this to point to the critsect itself. */
     337    RTR3PTR                             pvKey;
     338    /** Pointer to the VM - R3Ptr. */
     339    PVMR3                               pVMR3;
     340    /** Pointer to the VM - R0Ptr. */
     341    PVMR0                               pVMR0;
     342    /** Pointer to the VM - GCPtr. */
     343    PVMRC                               pVMRC;
     344#if HC_ARCH_BITS == 64
     345    /** Alignment padding. */
     346    RTRCPTR                             RCPtrPadding;
     347#endif
     348    /** The lock name. */
     349    R3PTRTYPE(const char *)             pszName;
     350    /** R0/RC write lock contention. */
     351    STAMCOUNTER                         StatContentionRZEnterExcl;
     352    /** R0/RC write unlock contention. */
     353    STAMCOUNTER                         StatContentionRZLeaveExcl;
     354    /** R0/RC read lock contention. */
     355    STAMCOUNTER                         StatContentionRZEnterShared;
     356    /** R0/RC read unlock contention. */
     357    STAMCOUNTER                         StatContentionRZLeaveShared;
     358    /** R0/RC writes. */
     359    STAMCOUNTER                         StatRZEnterExcl;
     360    /** R0/RC reads. */
     361    STAMCOUNTER                         StatRZEnterShared;
     362    /** R3 write lock contention. */
     363    STAMCOUNTER                         StatContentionR3EnterExcl;
     364    /** R3 read lock contention. */
     365    STAMCOUNTER                         StatContentionR3EnterShared;
     366    /** R3 writes. */
     367    STAMCOUNTER                         StatR3EnterExcl;
     368    /** R3 reads. */
     369    STAMCOUNTER                         StatR3EnterShared;
     370    /** Profiling the time the section is write locked. */
     371    STAMPROFILEADV                      StatWriteLocked;
     372} PDMCRITSECTRWINT;
     373AssertCompileMemberAlignment(PDMCRITSECTRWINT, StatContentionRZEnterExcl, 8);
     374AssertCompileMemberAlignment(PDMCRITSECTRWINT, Core.u64State, 8);
     375/** Pointer to private critical section data. */
     376typedef PDMCRITSECTRWINT *PPDMCRITSECTRWINT;
     377
     378
     379
     380/**
    312381 * The usual device/driver/internal/external stuff.
    313382 */
     
    355424#define PDMDRVINSINT_DECLARED
    356425#define PDMCRITSECTINT_DECLARED
     426#define PDMCRITSECTRWINT_DECLARED
    357427#define PDMTHREADINT_DECLARED
    358428#ifdef ___VBox_pdm_h
     
    9451015/**
    9461016 * PDM VMCPU Instance data.
    947  * Changes to this must checked against the padding of the cfgm union in VMCPU!
     1017 * Changes to this must checked against the padding of the pdm union in VMCPU!
    9481018 */
    9491019typedef struct PDMCPU
    9501020{
    951     /** The number of entries in the apQueuedCritSectsLeaves table that's currently in use. */
     1021    /** The number of entries in the apQueuedCritSectsLeaves table that's currently
     1022     * in use. */
    9521023    uint32_t                        cQueuedCritSectLeaves;
    9531024    uint32_t                        uPadding0; /**< Alignment padding.*/
    954     /** Critical sections queued in RC/R0 because of contention preventing leave to complete. (R3 Ptrs)
     1025    /** Critical sections queued in RC/R0 because of contention preventing leave to
     1026     * complete. (R3 Ptrs)
    9551027     * We will return to Ring-3 ASAP, so this queue doesn't have to be very long. */
    956     R3PTRTYPE(PPDMCRITSECT)         apQueuedCritSectsLeaves[8];
     1028    R3PTRTYPE(PPDMCRITSECT)         apQueuedCritSectLeaves[8];
     1029
     1030    /** The number of entries in the apQueuedCritSectRwExclLeaves table that's
     1031     * currently in use. */
     1032    uint32_t                        cQueuedCritSectRwExclLeaves;
     1033    uint32_t                        uPadding1; /**< Alignment padding.*/
     1034    /** Read/write critical sections queued in RC/R0 because of contention
     1035     * preventing exclusive leave to complete. (R3 Ptrs)
     1036     * We will return to Ring-3 ASAP, so this queue doesn't have to be very long. */
     1037    R3PTRTYPE(PPDMCRITSECTRW)       apQueuedCritSectRwExclLeaves[8];
     1038
     1039    /** The number of entries in the apQueuedCritSectsRwShrdLeaves table that's
     1040     * currently in use. */
     1041    uint32_t                        cQueuedCritSectRwShrdLeaves;
     1042    uint32_t                        uPadding2; /**< Alignment padding.*/
     1043    /** Read/write critical sections queued in RC/R0 because of contention
     1044     * preventing shared leave to complete. (R3 Ptrs)
     1045     * We will return to Ring-3 ASAP, so this queue doesn't have to be very long. */
     1046    R3PTRTYPE(PPDMCRITSECTRW)       apQueuedCritSectRwShrdLeaves[8];
    9571047} PDMCPU;
    9581048
     
    10731163    /** List of initialized critical sections. (LIFO) */
    10741164    R3PTRTYPE(PPDMCRITSECTINT)      pCritSects;
     1165    /** List of initialized read/write critical sections. (LIFO) */
     1166    R3PTRTYPE(PPDMCRITSECTRWINT)    pRwCritSects;
    10751167    /** Head of the PDM Thread list. (singly linked) */
    10761168    R3PTRTYPE(PPDMTHREAD)           pThreads;
     
    11551247bool        pdmR3IsValidName(const char *pszName);
    11561248
    1157 int         pdmR3CritSectInitStats(PVM pVM);
    1158 void        pdmR3CritSectRelocate(PVM pVM);
    1159 int         pdmR3CritSectInitDevice(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, va_list va);
    1160 int         pdmR3CritSectInitDeviceAuto(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
    1161                                         const char *pszNameFmt, ...);
    1162 int         pdmR3CritSectDeleteDevice(PVM pVM, PPDMDEVINS pDevIns);
    1163 int         pdmR3CritSectInitDriver(PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...);
    1164 int         pdmR3CritSectDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns);
     1249int         pdmR3CritSectBothInitStats(PVM pVM);
     1250void        pdmR3CritSectBothRelocate(PVM pVM);
     1251int         pdmR3CritSectBothDeleteDevice(PVM pVM, PPDMDEVINS pDevIns);
     1252int         pdmR3CritSectBothDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns);
     1253int         pdmR3CritSectInitDevice(        PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
     1254                                            const char *pszNameFmt, va_list va);
     1255int         pdmR3CritSectInitDeviceAuto(    PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
     1256                                            const char *pszNameFmt, ...);
     1257int         pdmR3CritSectInitDriver(        PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
     1258                                            const char *pszNameFmt, ...);
     1259int         pdmR3CritSectRwInitDevice(      PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     1260                                            const char *pszNameFmt, va_list va);
     1261int         pdmR3CritSectRwInitDeviceAuto(  PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     1262                                            const char *pszNameFmt, ...);
     1263int         pdmR3CritSectRwInitDriver(      PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
     1264                                            const char *pszNameFmt, ...);
    11651265
    11661266int         pdmR3DevInit(PVM pVM);
  • trunk/src/VBox/VMM/testcase/tstVMStruct.h

    r44528 r45152  
    463463    GEN_CHECK_OFF(PDM, pDevHlpQueueRC);
    464464    GEN_CHECK_OFF(PDMCPU, cQueuedCritSectLeaves);
    465     GEN_CHECK_OFF(PDMCPU, apQueuedCritSectsLeaves);
     465    GEN_CHECK_OFF(PDMCPU, apQueuedCritSectLeaves);
     466    GEN_CHECK_OFF(PDMCPU, cQueuedCritSectRwExclLeaves);
     467    GEN_CHECK_OFF(PDMCPU, apQueuedCritSectRwExclLeaves);
     468    GEN_CHECK_OFF(PDMCPU, cQueuedCritSectRwShrdLeaves);
     469    GEN_CHECK_OFF(PDMCPU, apQueuedCritSectRwShrdLeaves);
    466470    GEN_CHECK_OFF(PDM, pQueueFlushR0);
    467471    GEN_CHECK_OFF(PDM, pQueueFlushRC);
     
    537541    GEN_CHECK_OFF(PDMCRITSECTINT, StatContentionR3);
    538542    GEN_CHECK_OFF(PDMCRITSECTINT, StatLocked);
     543    GEN_CHECK_SIZE(PDMCRITSECT);
     544    GEN_CHECK_SIZE(PDMCRITSECTRWINT);
     545    GEN_CHECK_OFF(PDMCRITSECTRWINT, Core);
     546    GEN_CHECK_OFF(PDMCRITSECTRWINT, pNext);
     547    GEN_CHECK_OFF(PDMCRITSECTRWINT, pvKey);
     548    GEN_CHECK_OFF(PDMCRITSECTRWINT, pVMR3);
     549    GEN_CHECK_OFF(PDMCRITSECTRWINT, pVMR0);
     550    GEN_CHECK_OFF(PDMCRITSECTRWINT, pVMRC);
     551    GEN_CHECK_OFF(PDMCRITSECTRWINT, pszName);
     552    GEN_CHECK_OFF(PDMCRITSECTRWINT, StatContentionRZEnterExcl);
     553    GEN_CHECK_OFF(PDMCRITSECTRWINT, StatWriteLocked);
     554    GEN_CHECK_SIZE(PDMCRITSECTRW);
    539555    GEN_CHECK_SIZE(PDMQUEUE);
    540556    GEN_CHECK_OFF(PDMQUEUE, pNext);
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r45094 r45152  
    348348
    349349    CHECK_PADDING2(PDMCRITSECT);
     350    CHECK_PADDING2(PDMCRITSECTRW);
    350351
    351352    /* pgm */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette