VirtualBox

Changeset 25368 in vbox


Ignore:
Timestamp:
Dec 14, 2009 4:31:40 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55985
Message:

RTCritSect,PDMCritSect,iprt/lockvalidator.h: Reworked the deadlocking detection for critical sections and preparing for lock order validation. This change generalizes the RTCRITSECT::Strict data and moves it out of the RTCRITSECT, leaving a pointer behind. This saves a bit of space in release builds.

Location:
trunk
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pdmcritsect.h

    r23350 r25368  
    4848{
    4949    /** Padding. */
    50     uint8_t padding[HC_ARCH_BITS == 64 ? 0xb8 : 0xa8];
     50    uint8_t padding[HC_ARCH_BITS == 32 ? 0x80 : 0xc0];
    5151#ifdef PDMCRITSECTINT_DECLARED
    5252    /** The internal structure (not normally visible). */
     
    5757VMMR3DECL(int)      PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, const char *pszName);
    5858VMMDECL(int)        PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy);
     59VMMDECL(int)        PDMCritSectEnterDebug(PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL);
    5960VMMDECL(int)        PDMCritSectTryEnter(PPDMCRITSECT pCritSect);
     61VMMDECL(int)        PDMCritSectTryEnterDebug(PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
    6062VMMR3DECL(int)      PDMR3CritSectEnterEx(PPDMCRITSECT pCritSect, bool fCallRing3);
    6163VMMDECL(void)       PDMCritSectLeave(PPDMCRITSECT pCritSect);
     
    7577VMMR3DECL(void)     PDMR3CritSectLeaveAll(PVM pVM);
    7678
     79/* Strict build: Remap the two enter calls to the debug versions. */
     80#ifdef VBOX_STRICT
     81# ifdef ___iprt_asm_h
     82#  define PDMCritSectEnter(pCritSect, rcBusy)   PDMCritSectEnterDebug((pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
     83#  define PDMCritSectTryEnter(pCritSect)        PDMCritSectTryEnterDebug((pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
     84# else
     85#  define PDMCritSectEnter(pCritSect, rcBusy)   PDMCritSectEnterDebug((pCritSect), (rcBusy), 0, RT_SRC_POS)
     86#  define PDMCritSectTryEnter(pCritSect)        PDMCritSectTryEnterDebug((pCritSect), 0, RT_SRC_POS)
     87# endif
     88#endif
     89
    7790/** @} */
    7891
  • trunk/include/VBox/vm.h

    r24799 r25368  
    957957        struct REM  s;
    958958#endif
    959 
    960 /** @def VM_REM_SIZE
    961  * Must be multiple of 32 and coherent with REM_ENV_SIZE from REMInternal.h. */
    962 # define VM_REM_SIZE        0x11100
    963         uint8_t     padding[VM_REM_SIZE];   /* multiple of 32 */
     959        uint8_t     padding[0x11100];   /* multiple of 64 */
    964960    } rem;
    965961
  • trunk/include/iprt/critsect.h

    r25168 r25368  
    3333#include <iprt/cdefs.h>
    3434#include <iprt/types.h>
     35#include <iprt/lockvalidator.h>
    3536#ifdef IN_RING3
    3637#include <iprt/thread.h>
     
    7172    /** Magic used to validate the section state.
    7273     * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
    73     volatile uint32_t       u32Magic;
     74    volatile uint32_t                   u32Magic;
    7475    /** Number of lockers.
    7576     * -1 if the section is free. */
    76     volatile int32_t        cLockers;
     77    volatile int32_t                    cLockers;
    7778    /** The owner thread. */
    78     volatile RTNATIVETHREAD NativeThreadOwner;
     79    volatile RTNATIVETHREAD             NativeThreadOwner;
    7980    /** Number of nested enter operations performed.
    8081     * Greater or equal to 1 if owned, 0 when free.
    8182     */
    82     volatile int32_t        cNestings;
     83    volatile int32_t                    cNestings;
    8384    /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
    84     uint32_t                fFlags;
    85     /** The semaphore to wait for. */
    86     RTSEMEVENT              EventSem;
    87 
    88     /** Data only used in strict mode for detecting and debugging deadlocks. */
    89     struct RTCRITSECTSTRICT
    90     {
    91         /** Strict: The current owner thread. */
    92         RTTHREAD volatile                   ThreadOwner;
    93         /** Strict: Where the section was entered. */
    94         R3PTRTYPE(const char * volatile)    pszEnterFile;
    95         /** Strict: Where the section was entered. */
    96         uint32_t volatile                   u32EnterLine;
    97 #if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
    98         /** Padding for correct alignment. */
    99         uint32_t                            u32Padding;
    100 #endif
    101         /** Strict: Where the section was entered. */
    102         RTUINTPTR volatile                  uEnterId;
    103     } Strict;
     85    uint32_t                            fFlags;
     86    /** The semaphore to block on. */
     87    RTSEMEVENT                          EventSem;
     88    /** Lock validator record.  Only used in strict builds. */
     89    R3R0PTRTYPE(PRTLOCKVALIDATORREC)    pValidatorRec;
     90    /** Alignmnet padding. */
     91    RTHCPTR                             Alignment;
    10492} RTCRITSECT;
     93AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
    10594/** Pointer to a critical section. */
    10695typedef RTCRITSECT *PRTCRITSECT;
     
    10897typedef const RTCRITSECT *PCRTCRITSECT;
    10998
    110 /** RTCRITSECT::u32Magic value. */
    111 #define RTCRITSECT_MAGIC    0x778899aa
     99/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
     100#define RTCRITSECT_MAGIC                UINT32_C(0x19790326)
    112101
    113102/** If set, nesting(/recursion) is not allowed. */
    114 #define RTCRITSECT_FLAGS_NO_NESTING     1
     103#define RTCRITSECT_FLAGS_NO_NESTING     UINT32_C(0x00000001)
    115104
    116105#ifdef IN_RING3
     
    143132 * Enter a critical section.
    144133 *
    145  * @returns VINF_SUCCESS on success.
    146  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    147  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    148  * @param   pCritSect   The critical section.
    149  * @param   pszFile     Where we're entering the section.
    150  * @param   uLine       Where we're entering the section.
    151  * @param   uId         Where we're entering the section.
    152  */
    153 RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId);
    154 
    155 /* in debug mode we'll redefine the enter call. */
    156 #ifdef RT_STRICT
    157 # define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, __FILE__,  __LINE__, 0)
    158 #endif
     134 * @retval  VINF_SUCCESS on success.
     135 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     136 * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     137 *
     138 * @param   pCritSect       The critical section.
     139 * @param   uId             Where we're entering the section.
     140 * @param   RT_SRC_POS_DECL The source position.
     141 */
     142RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
    159143
    160144/**
    161145 * Try enter a critical section.
    162146 *
    163  * @returns VINF_SUCCESS on success.
    164  * @returns VERR_SEM_BUSY if the critsect was owned.
    165  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    166  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     147 * @retval  VINF_SUCCESS on success.
     148 * @retval  VERR_SEM_BUSY if the critsect was owned.
     149 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     150 * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     151 *
    167152 * @param   pCritSect   The critical section.
    168153 */
     
    172157 * Try enter a critical section.
    173158 *
    174  * @returns VINF_SUCCESS on success.
    175  * @returns VERR_SEM_BUSY if the critsect was owned.
    176  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    177  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    178  * @param   pCritSect   The critical section.
    179  * @param   pszFile     Where we're entering the section.
    180  * @param   uLine       Where we're entering the section.
    181  * @param   uId         Where we're entering the section.
    182  */
    183 RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId);
    184 
    185 /* in debug mode we'll redefine the try-enter call. */
    186 #ifdef RT_STRICT
    187 # define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, __FILE__,  __LINE__, 0)
    188 #endif
     159 * @retval  VINF_SUCCESS on success.
     160 * @retval  VERR_SEM_BUSY if the critsect was owned.
     161 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     162 * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     163 *
     164 * @param   pCritSect       The critical section.
     165 * @param   uId             Where we're entering the section.
     166 * @param   RT_SRC_POS_DECL The source position.
     167 */
     168RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
    189169
    190170/**
     
    203183 *          Therefore, avoid having to enter multiple critical sections!
    204184 */
    205 RTDECL(int) RTCritSectEnterMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects);
     185RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
    206186
    207187/**
     
    216196 * @param   cCritSects      Number of critical sections in the array.
    217197 * @param   papCritSects    Array of critical section pointers.
    218  * @param   pszFile         Where we're entering the section.
    219  * @param   uLine           Where we're entering the section.
    220198 * @param   uId             Where we're entering the section.
     199 * @param   RT_SRC_POS_DECL The source position.
    221200 *
    222201 * @remark  See RTCritSectEnterMultiple().
    223202 */
    224 RTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId);
    225 
    226 /* in debug mode we'll redefine the enter-multiple call. */
    227 #ifdef RT_STRICT
    228 # define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), __FILE__,  __LINE__, 0)
    229 #endif
     203RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL);
    230204
    231205/**
     
    244218 * @param   papCritSects    Array of critical section pointers.
    245219 */
    246 RTDECL(int) RTCritSectLeaveMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects);
     220RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
    247221
    248222/**
     
    326300}
    327301
     302/* Strict build: Remap the three enter calls to the debug versions. */
     303#ifdef RT_STRICT
     304# ifdef ___iprt_asm_h
     305#  define RTCritSectEnter(pCritSect)                        RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
     306#  define RTCritSectTryEnter(pCritSect)                     RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
     307#  define RTCritSectEnterMultiple(cCritSects, pCritSect)    RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
     308# else
     309#  define RTCritSectEnter(pCritSect)                        RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS)
     310#  define RTCritSectTryEnter(pCritSect)                     RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS)
     311#  define RTCritSectEnterMultiple(cCritSects, pCritSect)    RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 0, RT_SRC_POS)
     312# endif
     313#endif
     314
    328315/** @} */
    329316
  • trunk/include/iprt/thread.h

    r25295 r25368  
    6161    /** Probably running. */
    6262    RTTHREADSTATE_RUNNING,
     63
    6364    /** Waiting on a critical section. */
    6465    RTTHREADSTATE_CRITSECT,
    65     /** Waiting on a mutex. */
    66     RTTHREADSTATE_MUTEX,
    6766    /** Waiting on a event semaphore. */
    6867    RTTHREADSTATE_EVENT,
    6968    /** Waiting on a event multiple wakeup semaphore. */
    70     RTTHREADSTATE_EVENTMULTI,
     69    RTTHREADSTATE_EVENT_MULTI,
     70    /** Waiting on a fast mutex. */
     71    RTTHREADSTATE_FAST_MUTEX,
     72    /** Waiting on a mutex. */
     73    RTTHREADSTATE_MUTEX,
    7174    /** Waiting on a read write semaphore, read (shared) access. */
    7275    RTTHREADSTATE_RW_READ,
     
    7578    /** The thread is sleeping. */
    7679    RTTHREADSTATE_SLEEP,
     80    /** Waiting on a spin mutex. */
     81    RTTHREADSTATE_SPIN_MUTEX,
     82
    7783    /** The usual 32-bit size hack. */
    7884    RTTHREADSTATE_32BIT_HACK = 0x7fffffff
     
    8086
    8187/** Checks if a thread state indicates that the thread is sleeping. */
    82 #define RTTHREAD_IS_SLEEPING(enmState) (    (enmState) == RTTHREADSTATE_CRITSECT \
    83                                         ||  (enmState) == RTTHREADSTATE_MUTEX \
    84                                         ||  (enmState) == RTTHREADSTATE_EVENT \
    85                                         ||  (enmState) == RTTHREADSTATE_EVENTMULTI \
    86                                         ||  (enmState) == RTTHREADSTATE_RW_READ \
    87                                         ||  (enmState) == RTTHREADSTATE_RW_WRITE \
    88                                         ||  (enmState) == RTTHREADSTATE_SLEEP \
    89                                        )
     88#define RTTHREAD_IS_SLEEPING(enmState) ((enmState) >= RTTHREADSTATE_CRITSECT)
    9089
    9190/**
     
    638637 * This is a RT_STRICT method for debugging locks and detecting deadlocks.
    639638 *
    640  * @param   hThread     The current thread.
    641  * @param   enmState    The sleep state.
    642  * @param   u64Block    The block data. A pointer or handle.
    643  * @param   pszFile     Where we are blocking.
    644  * @param   uLine       Where we are blocking.
    645  * @param   uId         Where we are blocking.
    646  */
    647 RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, uint64_t u64Block,
    648                               const char *pszFile, unsigned uLine, RTUINTPTR uId);
     639 * @param   hThread         The current thread.
     640 * @param   enmState        The sleep state.
     641 * @param   pvBlock         Pointer to a RTLOCKVALIDATORREC structure.
     642 * @param   uId             Where we are blocking.
     643 * @param   RT_SRC_POS_DECL Where we are blocking.
     644 */
     645RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState,
     646                              PRTLOCKVALIDATORREC pValidatorRec, RTHCUINTPTR uId, RT_SRC_POS_DECL);
    649647
    650648
  • trunk/include/iprt/types.h

    r25310 r25368  
    11241124#define NIL_RTLDRMOD                                0
    11251125
     1126/** Lock validator class handle. */
     1127typedef R3R0PTRTYPE(struct RTLOCKVALIDATORCLASSINT *) RTLOCKVALIDATORCLASS;
     1128/** Pointer to a lock validator class handle. */
     1129typedef RTLOCKVALIDATORCLASS                       *PRTLOCKVALIDATORCLASS;
     1130/** Nil lock validator class handle. */
     1131#define NIL_RTLOCKVALIDATORCLASS                    ((RTLOCKVALIDATORCLASS)0)
     1132
    11261133/** Ring-0 memory object handle. */
    11271134typedef R0PTRTYPE(struct RTR0MEMOBJINTERNAL *)      RTR0MEMOBJ;
     
    14601467
    14611468
     1469/** Pointer to a lock validator record.
     1470 * The structure definition is found in iprt/lockvalidator.h.  */
     1471typedef struct RTLOCKVALIDATORREC *PRTLOCKVALIDATORREC;
     1472
     1473
    14621474#ifdef __cplusplus
    14631475/**
  • trunk/src/VBox/Main/AutoLock.cpp

    r25350 r25368  
    292292#endif
    293293
    294 #if defined(DEBUG) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
    295     RTCritSectEnterDebug(&m->sem, pszFile, iLine, (uintptr_t)ASMReturnAddress());
    296 #elif defined(DEBUG)
    297     RTCritSectEnterDebug(&m->sem,
    298                          "WriteLockHandle::lockWrite() return address >>>",
    299                          0, (RTUINTPTR)ASMReturnAddress());
     294#if defined(RT_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
     295    RTCritSectEnterDebug(&m->sem, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
     296#elif defined(RT_STRICT)
     297    RTCritSectEnterDebug(&m->sem, (uintptr_t)ASMReturnAddress(),
     298                         "return address >>>", 0, __PRETTY_FUNCTION__);
    300299#else
    301300    RTCritSectEnter(&m->sem);
  • trunk/src/VBox/Runtime/Makefile.kmk

    r25296 r25368  
    240240        common/misc/handletablectx.cpp \
    241241        common/misc/handletablesimple.cpp \
     242        common/misc/lockvalidator.cpp \
    242243        common/misc/message.cpp \
    243244        common/misc/once.cpp \
     
    12571258
    12581259RuntimeR0Drv_SOURCES.win = \
     1260        common/misc/lockvalidator.cpp \
    12591261        common/misc/thread.cpp \
    12601262        common/string/memcmp.asm \
     
    12991301        common/misc/RTAssertMsg1Weak.cpp \
    13001302        common/misc/RTAssertMsg2Weak.cpp \
     1303        common/misc/lockvalidator.cpp \
    13011304        common/misc/thread.cpp \
    13021305        common/string/memchr.asm \
     
    13431346        common/string/strpbrk.cpp \
    13441347        \
     1348        common/misc/lockvalidator.cpp \
    13451349        common/misc/thread.cpp \
    13461350        generic/RTAssertShouldPanic-generic.cpp \
     
    13901394        common/err/RTErrConvertFromErrno.cpp \
    13911395        common/err/RTErrConvertToErrno.cpp \
     1396        common/misc/lockvalidator.cpp \
    13921397        common/misc/thread.cpp \
    13931398        common/string/memchr.asm \
     
    14241429        common/err/RTErrConvertFromErrno.cpp \
    14251430        common/err/RTErrConvertToErrno.cpp \
     1431        common/misc/lockvalidator.cpp \
    14261432        common/misc/thread.cpp \
    14271433        common/string/memchr.asm \
  • trunk/src/VBox/Runtime/common/misc/thread.cpp

    r25000 r25368  
    4141#include <iprt/alloc.h>
    4242#include <iprt/assert.h>
     43#include <iprt/lockvalidator.h>
    4344#include <iprt/semaphore.h>
    4445#ifdef IN_RING0
     
    4849#include <iprt/err.h>
    4950#include <iprt/string.h>
     51#include "internal/magics.h"
    5052#include "internal/thread.h"
    5153#include "internal/sched.h"
     
    195197
    196198
     199/**
     200 * Gets the thread state.
     201 *
     202 * @returns The thread state.
     203 * @param   pThread             The thread.
     204 */
     205DECLINLINE(RTTHREADSTATE) rtThreadGetState(PRTTHREADINT pThread)
     206{
     207    return pThread->enmState;
     208}
     209
     210
     211/**
     212 * Sets the thread state.
     213 *
     214 * @param   pThread             The thread.
     215 * @param   enmNewState         The new thread state.
     216 */
     217DECLINLINE(void) rtThreadSetState(PRTTHREADINT pThread, RTTHREADSTATE enmNewState)
     218{
     219    AssertCompile(sizeof(pThread->enmState) == sizeof(uint32_t));
     220    ASMAtomicWriteU32((uint32_t volatile *)&pThread->enmState, enmNewState);
     221}
    197222
    198223#ifdef IN_RING3
     
    255280        {
    256281            rtThreadInsert(pThread, NativeThread);
    257             ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING);
     282            rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
    258283            rtThreadRelease(pThread);
    259284        }
     
    376401     * it should not be reinserted at this point.
    377402     */
    378     if (pThread->enmState != RTTHREADSTATE_TERMINATED)
     403    if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED)
    379404    {
    380405        /*
     
    588613     */
    589614    pThread->rc = rc;
    590     ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_TERMINATED);
     615    rtThreadSetState(pThread, RTTHREADSTATE_TERMINATED);
    591616    ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED);
    592617    if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI)
     
    634659     * Call thread function and terminate when it returns.
    635660     */
    636     ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING);
     661    rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
    637662    rc = pThread->pfnThread(pThread, pThread->pvUser);
    638663
     
    13801405
    13811406/**
     1407 * Translate a thread state into a string.
     1408 *
     1409 * @returns Pointer to a read-only string containing the state name.
     1410 * @param   enmState            The state.
     1411 */
     1412static const char *rtThreadStateName(RTTHREADSTATE enmState)
     1413{
     1414    switch (enmState)
     1415    {
     1416        case RTTHREADSTATE_INVALID:         return "INVALID";
     1417        case RTTHREADSTATE_INITIALIZING:    return "INITIALIZING";
     1418        case RTTHREADSTATE_TERMINATED:      return "TERMINATED";
     1419        case RTTHREADSTATE_RUNNING:         return "RUNNING";
     1420        case RTTHREADSTATE_CRITSECT:        return "CRITSECT";
     1421        case RTTHREADSTATE_EVENT:           return "EVENT";
     1422        case RTTHREADSTATE_EVENT_MULTI:     return "EVENT_MULTI";
     1423        case RTTHREADSTATE_FAST_MUTEX:      return "FAST_MUTEX";
     1424        case RTTHREADSTATE_MUTEX:           return "MUTEX";
     1425        case RTTHREADSTATE_RW_READ:         return "RW_READ";
     1426        case RTTHREADSTATE_RW_WRITE:        return "RW_WRITE";
     1427        case RTTHREADSTATE_SLEEP:           return "SLEEP";
     1428        case RTTHREADSTATE_SPIN_MUTEX:      return "SPIN_MUTEX";
     1429        default:                            return "UnknownThreadState";
     1430    }
     1431}
     1432
     1433
     1434/**
    13821435 * Bitch about a deadlock.
    13831436 *
    1384  * @param   pThread     This thread.
    1385  * @param   pCur        The thread we're deadlocking with.
    1386  * @param   enmState    The sleep state.
    1387  * @param   u64Block    The block data. A pointer or handle.
    1388  * @param   pszFile     Where we are gonna block.
    1389  * @param   uLine       Where we are gonna block.
    1390  * @param   uId         Where we are gonna block.
    1391  */
    1392 static void rtThreadDeadlock(PRTTHREADINT pThread, PRTTHREADINT pCur, RTTHREADSTATE enmState, uint64_t u64Block,
    1393                              const char *pszFile, unsigned uLine, RTUINTPTR uId)
    1394 {
    1395     AssertMsg1(pCur == pThread ? "!!Deadlock detected!!" : "!!Deadlock exists!!", uLine, pszFile, "");
     1437 * @param   pThread         This thread.
     1438 * @param   pCur            The thread we're deadlocking with.
     1439 * @param   enmState        The sleep state.
     1440 * @param   pRec            The lock validator record we're going to block on.
     1441 * @param   RT_SRC_POS_DECL Where we are going to deadlock.
     1442 * @param   uId             Where we are going to deadlock.
     1443 */
     1444static void rtThreadDeadlock(PRTTHREADINT pThread, PRTTHREADINT pCur, RTTHREADSTATE enmState,
     1445                             PRTLOCKVALIDATORREC pRec, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     1446{
     1447    AssertMsg1(pCur == pThread ? "!!Deadlock detected!!" : "!!Deadlock exists!!", iLine, pszFile, pszFunction);
    13961448
    13971449    /*
     
    14061458         * Print info on pCur. Determin next while doing so.
    14071459         */
    1408         AssertMsg2(" #%d: %RTthrd/%RTnthrd %s: %s(%u) %RTptr\n",
     1460        AssertMsg2(" #%u: %RTthrd/%RTnthrd %s: %s(%u) %RTptr\n",
    14091461                   iEntry, pCur, pCur->Core.Key, pCur->szName,
    1410                    pCur->pszBlockFile, pCur->uBlockLine, pCur->uBlockId);
    1411         PRTTHREADINT pNext = NULL;
    1412         switch (pCur->enmState)
     1462                   pCur->pszBlockFile, pCur->uBlockLine, pCur->pszBlockFunction, pCur->uBlockId);
     1463        PRTTHREADINT  pNext       = NULL;
     1464        RTTHREADSTATE enmCurState = rtThreadGetState(pCur);
     1465        switch (enmCurState)
    14131466        {
    14141467            case RTTHREADSTATE_CRITSECT:
     1468            case RTTHREADSTATE_EVENT:
     1469            case RTTHREADSTATE_EVENT_MULTI:
     1470            case RTTHREADSTATE_FAST_MUTEX:
     1471            case RTTHREADSTATE_MUTEX:
     1472            case RTTHREADSTATE_RW_READ:
     1473            case RTTHREADSTATE_RW_WRITE:
     1474            case RTTHREADSTATE_SPIN_MUTEX:
    14151475            {
    1416                 PRTCRITSECT pCritSect = pCur->Block.pCritSect;
    1417                 if (pCur->enmState != RTTHREADSTATE_CRITSECT)
     1476                PRTLOCKVALIDATORREC pCurRec      = pCur->Block.pRec;
     1477                RTTHREADSTATE       enmCurState2 = rtThreadGetState(pCur);
     1478                if (enmCurState2 != enmCurState)
    14181479                {
    1419                     AssertMsg2("Impossible!!!\n");
     1480                    AssertMsg2(" Impossible!!! enmState=%s -> %s (%d)\n",
     1481                               rtThreadStateName(enmCurState), rtThreadStateName(enmCurState2), enmCurState2);
    14201482                    break;
    14211483                }
    1422                 if (VALID_PTR(pCritSect) && RTCritSectIsInitialized(pCritSect))
     1484                if (   VALID_PTR(pCurRec)
     1485                    && pCurRec->u32Magic == RTLOCKVALIDATORREC_MAGIC)
    14231486                {
    1424                     AssertMsg2("     Waiting on CRITSECT %p: Entered %s(%u) %RTptr\n",
    1425                                pCritSect, pCritSect->Strict.pszEnterFile,
    1426                                pCritSect->Strict.u32EnterLine, pCritSect->Strict.uEnterId);
    1427                     pNext = pCritSect->Strict.ThreadOwner;
     1487                    AssertMsg2("     Waiting on %s %p [%s]: Entered %s(%u) %s %p\n",
     1488                               rtThreadStateName(enmCurState), pCurRec->hLock, pCurRec->pszName,
     1489                               pCurRec->pszFile, pCurRec->uLine, pCurRec->pszFunction, pCurRec->uId);
     1490                    pNext = pCurRec->hThread;
    14281491                }
     1492                else if (VALID_PTR(pCurRec))
     1493                    AssertMsg2("     Waiting on %s pCurRec=%p: invalid magic number: %#x\n",
     1494                               rtThreadStateName(enmCurState), pCurRec, pCurRec->u32Magic);
    14291495                else
    1430                     AssertMsg2("     Waiting on CRITSECT %p: invalid pointer or uninitialized critsect\n", pCritSect);
     1496                    AssertMsg2("     Waiting on %s pCurRec=%p: invalid pointer\n",
     1497                               rtThreadStateName(enmCurState), pCurRec);
    14311498                break;
    14321499            }
    14331500
    14341501            default:
    1435                 AssertMsg2(" Impossible!!! enmState=%d\n", pCur->enmState);
     1502                AssertMsg2(" Impossible!!! enmState=%s (%d)\n", rtThreadStateName(enmCurState), enmCurState);
    14361503                break;
    14371504        }
     
    14661533 * This is a RT_STRICT method for debugging locks and detecting deadlocks.
    14671534 *
    1468  * @param   hThread     The current thread.
    1469  * @param   enmState    The sleep state.
    1470  * @param   u64Block    The block data. A pointer or handle.
    1471  * @param   pszFile     Where we are blocking.
    1472  * @param   uLine      Where we are blocking.
    1473  * @param   uId         Where we are blocking.
    1474  */
    1475 RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, uint64_t u64Block,
    1476                               const char *pszFile, unsigned uLine, RTUINTPTR uId)
     1535 * @param   hThread         The current thread.
     1536 * @param   enmState        The sleep state.
     1537 * @param   pvBlock         Pointer to a RTLOCKVALIDATORREC structure.
     1538 * @param   uId             Where we are blocking.
     1539 * @param   RT_SRC_POS_DECL Where we are blocking.
     1540 */
     1541RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState,
     1542                              PRTLOCKVALIDATORREC pValidatorRec, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     1543
    14771544{
    14781545    PRTTHREADINT pThread = hThread;
    14791546    Assert(RTTHREAD_IS_SLEEPING(enmState));
    1480     if (pThread && pThread->enmState == RTTHREADSTATE_RUNNING)
     1547    if (pThread && rtThreadGetState(pThread) == RTTHREADSTATE_RUNNING)
    14811548    {
    14821549        /** @todo This has to be serialized! The deadlock detection isn't 100% safe!!! */
    1483         pThread->Block.u64      = u64Block;
    1484         pThread->pszBlockFile   = pszFile;
    1485         pThread->uBlockLine     = uLine;
    1486         pThread->uBlockId       = uId;
    1487         ASMAtomicWriteSize(&pThread->enmState, enmState);
     1550        pThread->Block.pRec         = pValidatorRec;
     1551        pThread->pszBlockFunction   = pszFunction;
     1552        pThread->pszBlockFile       = pszFile;
     1553        pThread->uBlockLine         = iLine;
     1554        pThread->uBlockId           = uId;
     1555        rtThreadSetState(pThread, enmState);
    14881556
    14891557        /*
     
    14971565        PRTTHREADINT    pCur;
    14981566        unsigned        cPrevLength = ~0U;
    1499         unsigned        cEqualRuns = 0;
    1500         unsigned        iParanoia = 256;
     1567        unsigned        cEqualRuns  = 0;
     1568        unsigned        iParanoia   = 256;
    15011569        do
    15021570        {
     
    15081576                 * Get the next thread.
    15091577                 */
     1578                PRTTHREADINT pNext = NULL;
    15101579                for (;;)
    15111580                {
    1512                     switch (pCur->enmState)
     1581                    RTTHREADSTATE enmCurState = rtThreadGetState(pCur);
     1582                    switch (enmCurState)
    15131583                    {
    15141584                        case RTTHREADSTATE_CRITSECT:
     1585                        case RTTHREADSTATE_EVENT:
     1586                        case RTTHREADSTATE_EVENT_MULTI:
     1587                        case RTTHREADSTATE_FAST_MUTEX:
     1588                        case RTTHREADSTATE_MUTEX:
     1589                        case RTTHREADSTATE_RW_READ:
     1590                        case RTTHREADSTATE_RW_WRITE:
     1591                        case RTTHREADSTATE_SPIN_MUTEX:
    15151592                        {
    1516                             PRTCRITSECT pCritSect = pCur->Block.pCritSect;
    1517                             if (pCur->enmState != RTTHREADSTATE_CRITSECT)
     1593                            PRTLOCKVALIDATORREC pRec = pCur->Block.pRec;
     1594                            if (    rtThreadGetState(pCur) != enmCurState
     1595                                ||  !VALID_PTR(pRec)
     1596                                ||  pRec->u32Magic != RTLOCKVALIDATORREC_MAGIC)
    15181597                                continue;
    1519                             pCur = pCritSect->Strict.ThreadOwner;
     1598                            pNext = pRec->hThread;
     1599                            if (    rtThreadGetState(pCur) != enmCurState
     1600                                ||  pRec->u32Magic != RTLOCKVALIDATORREC_MAGIC
     1601                                ||  pRec->hThread != pNext)
     1602                                continue;
    15201603                            break;
    15211604                        }
    15221605
    15231606                        default:
    1524                             pCur = NULL;
     1607                            pNext = NULL;
    15251608                            break;
    15261609                    }
    15271610                    break;
    15281611                }
     1612
     1613                /*
     1614                 * If we arrive at the end of the list we're good.
     1615                 */
     1616                pCur = pNext;
    15291617                if (!pCur)
    15301618                    return;
    15311619
    15321620                /*
    1533                  * If we've got back to the blocking thread id we've got a deadlock.
    1534                  * If we've got a chain of more than 256 items, there is some kind of cycle
    1535                  * in the list, which means that there is already a deadlock somewhere.
     1621                 * If we've got back to the blocking thread id we've
     1622                 * got a deadlock.
    15361623                 */
    1537                 if (pCur == pThread || cLength >= 256)
     1624                if (pCur == pThread)
    15381625                    break;
     1626
     1627                /*
     1628                 * If we've got a chain of more than 256 items, there is some
     1629                 * kind of cycle in the list, which means that there is already
     1630                 * a deadlock somewhere.
     1631                 */
     1632                if (cLength >= 256)
     1633                    break;
     1634
    15391635                cLength++;
    15401636            }
     
    15531649         * Ok, if we ever get here, it's most likely a genuine deadlock.
    15541650         */
    1555         rtThreadDeadlock(pThread, pCur, enmState, u64Block, pszFile, uLine, uId);
     1651        rtThreadDeadlock(pThread, pCur, enmState, pValidatorRec, uId, RT_SRC_POS_ARGS);
    15561652    }
    15571653}
     
    15701666RTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState)
    15711667{
    1572     if (hThread && hThread->enmState == enmCurState)
    1573         ASMAtomicWriteSize(&hThread->enmState, RTTHREADSTATE_RUNNING);
     1668    if (hThread && rtThreadGetState(hThread) == enmCurState)
     1669        rtThreadSetState(hThread, RTTHREADSTATE_RUNNING);
    15741670}
    15751671RT_EXPORT_SYMBOL(RTThreadUnblocked);
  • trunk/src/VBox/Runtime/generic/critsect-generic.cpp

    r23718 r25368  
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4545
    4646
    47 /* in strict mode we're redefining this, so undefine it now for the implementation. */
     47/* In strict mode we're redefining these, so undefine them now for the implementation. */
    4848#undef RTCritSectEnter
    4949#undef RTCritSectTryEnter
     
    5151
    5252
    53 /**
    54  * Initialize a critical section.
    55  */
    5653RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect)
    5754{
     
    6158
    6259
    63 /**
    64  * Initialize a critical section.
    65  *
    66  * @returns iprt status code.
    67  * @param   pCritSect   Pointer to the critical section structure.
    68  * @param   fFlags      Flags, any combination of the RTCRITSECT_FLAGS \#defines.
    69  */
    7060RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags)
    7161{
     
    7868    pCritSect->cLockers             = -1;
    7969    pCritSect->NativeThreadOwner    = NIL_RTNATIVETHREAD;
    80     pCritSect->Strict.ThreadOwner   = NIL_RTTHREAD;
    81     pCritSect->Strict.pszEnterFile  = NULL;
    82     pCritSect->Strict.u32EnterLine  = 0;
    83     pCritSect->Strict.uEnterId      = 0;
    84     int rc = RTSemEventCreate(&pCritSect->EventSem);
     70    int rc = RTLockValidatorCreate(&pCritSect->pValidatorRec, NIL_RTLOCKVALIDATORCLASS, 0, NULL, pCritSect);
    8571    if (RT_SUCCESS(rc))
    86         return VINF_SUCCESS;
     72    {
     73        rc = RTSemEventCreate(&pCritSect->EventSem);
     74        if (RT_SUCCESS(rc))
     75            return VINF_SUCCESS;
     76        RTLockValidatorDestroy(&pCritSect->pValidatorRec);
     77    }
    8778
    8879    AssertRC(rc);
     
    9485
    9586
    96 /**
    97  * Enter multiple critical sections.
    98  *
    99  * This function will enter ALL the specified critical sections before returning.
    100  *
    101  * @returns VINF_SUCCESS on success.
    102  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    103  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    104  * @param   cCritSects      Number of critical sections in the array.
    105  * @param   papCritSects    Array of critical section pointers.
    106  *
    107  * @remark  Please note that this function will not necessarily come out favourable in a
    108  *          fight with other threads which are using the normal RTCritSectEnter() function.
    109  *          Therefore, avoid having to enter multiple critical sections!
    110  */
    111 RTDECL(int) RTCritSectEnterMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects)
    112 #ifdef RTCRITSECT_STRICT
    113 {
    114     return RTCritSectEnterMultipleDebug(cCritSects, papCritSects, __FILE__, __LINE__, 0);
    115 }
    116 RTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    117 #endif /* RTCRITSECT_STRICT */
     87#ifdef RTCRITSECT_STRICT
     88RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL)
     89#else
     90RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
     91#endif
    11892{
    11993    Assert(cCritSects > 0);
    120     Assert(VALID_PTR(papCritSects));
     94    AssertPtr(papCritSects);
    12195
    12296    /*
     
    12498     */
    12599    int rc = VERR_INVALID_PARAMETER;
    126     unsigned i;
     100    size_t i;
    127101    for (i = 0; i < cCritSects; i++)
    128102    {
    129103#ifdef RTCRITSECT_STRICT
    130         rc = RTCritSectTryEnterDebug(papCritSects[i], pszFile, uLine, uId);
     104        rc = RTCritSectTryEnterDebug(papCritSects[i], uId, RT_SRC_POS_ARGS);
    131105#else
    132106        rc = RTCritSectTryEnter(papCritSects[i]);
     
    146120         * We've failed, release any locks we might have gotten. ('i' is the lock that failed btw.)
    147121         */
    148         unsigned j = i;
     122        size_t j = i;
    149123        while (j-- > 0)
    150124        {
     
    166140         */
    167141#ifdef RTCRITSECT_STRICT
    168         rc = RTCritSectEnterDebug(papCritSects[i], pszFile, uLine, uId);
     142        rc = RTCritSectEnterDebug(papCritSects[i], uId, RT_SRC_POS_ARGS);
    169143#else
    170144        rc = RTCritSectEnter(papCritSects[i]);
     
    181155            {
    182156#ifdef RTCRITSECT_STRICT
    183                 rc = RTCritSectTryEnterDebug(papCritSects[j], pszFile, uLine, uId);
     157                rc = RTCritSectTryEnterDebug(papCritSects[j], uId, RT_SRC_POS_ARGS);
    184158#else
    185159                rc = RTCritSectTryEnter(papCritSects[j]);
     
    203177    }
    204178}
     179#ifdef RTCRITSECT_STRICT
     180RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
     181#else
    205182RT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
    206 
    207 
    208 /**
    209  * Try enter a critical section.
    210  *
    211  * @returns VINF_SUCCESS on success.
    212  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    213  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    214  * @param   pCritSect   The critical section.
    215  */
     183#endif
     184
     185
     186#ifdef RTCRITSECT_STRICT
     187RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
     188{
     189    return RTCritSectEnterMultipleDebug(cCritSects, papCritSects, 0, RT_SRC_POS);
     190}
     191RT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
     192
     193
     194#else  /* !RTCRITSECT_STRICT */
     195RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL)
     196{
     197    return RTCritSectEnterMultiple(cCritSects, papCritSects);
     198}
     199RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
     200#endif /* !RTCRITSECT_STRICT */
     201
     202
     203#ifdef RTCRITSECT_STRICT
     204RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     205#else
    216206RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
    217 #ifdef RTCRITSECT_STRICT
    218 {
    219     return RTCritSectTryEnterDebug(pCritSect, __FILE__, __LINE__, 0);
    220 }
    221 RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    222 #endif /* RTCRITSECT_STRICT */
     207#endif
    223208{
    224209    Assert(pCritSect);
     
    259244    ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
    260245#ifdef RTCRITSECT_STRICT
    261     pCritSect->Strict.pszEnterFile = pszFile;
    262     pCritSect->Strict.u32EnterLine = uLine;
    263     pCritSect->Strict.uEnterId     = uId;
    264     ASMAtomicWriteHandle(&pCritSect->Strict.ThreadOwner, ThreadSelf);
     246    RTLockValidatorSetOwner(pCritSect->pValidatorRec, ThreadSelf, uId, RT_SRC_POS_ARGS);
    265247#endif
    266248
    267249    return VINF_SUCCESS;
    268250}
     251#ifdef RTCRITSECT_STRICT
     252RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
     253#else
    269254RT_EXPORT_SYMBOL(RTCritSectTryEnter);
    270 
    271 
    272 /**
    273  * Enter a critical section.
    274  *
    275  * @returns VINF_SUCCESS on success.
    276  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    277  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    278  * @param   pCritSect   The critical section.
    279  */
     255#endif
     256
     257
     258#ifdef RTCRITSECT_STRICT
     259RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
     260{
     261    return RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS);
     262}
     263RT_EXPORT_SYMBOL(RTCritSectTryEnter);
     264
     265
     266#else  /* !RTCRITSECT_STRICT */
     267RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     268{
     269    return RTCritSectTryEnter(pCritSect);
     270}
     271RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
     272#endif /* !RTCRITSECT_STRICT */
     273
     274
     275#ifdef RTCRITSECT_STRICT
     276RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     277#else
    280278RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
    281 #ifdef RTCRITSECT_STRICT
    282 {
    283     return RTCritSectEnterDebug(pCritSect, __FILE__, __LINE__, 0);
    284 }
    285 RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    286 #endif /* RTCRITSECT_STRICT */
     279#endif
    287280{
    288281    Assert(pCritSect);
     
    293286    if (ThreadSelf == NIL_RTTHREAD)
    294287        RTThreadAdopt(RTTHREADTYPE_DEFAULT, 0, NULL, &ThreadSelf);
     288    RTLockValidatorCheckOrder(pCritSect->pValidatorRec, ThreadSelf, uId, RT_SRC_POS_ARGS);
    295289#endif
    296290
     
    324318        {
    325319#ifdef RTCRITSECT_STRICT
    326             RTThreadBlocking(ThreadSelf, RTTHREADSTATE_CRITSECT, (uintptr_t)pCritSect, pszFile, uLine, uId);
     320            RTThreadBlocking(ThreadSelf, RTTHREADSTATE_CRITSECT, pCritSect->pValidatorRec, uId, RT_SRC_POS_ARGS);
    327321#endif
    328322            int rc = RTSemEventWait(pCritSect->EventSem, RT_INDEFINITE_WAIT);
     
    345339    ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
    346340#ifdef RTCRITSECT_STRICT
    347     pCritSect->Strict.pszEnterFile = pszFile;
    348     pCritSect->Strict.u32EnterLine = uLine;
    349     pCritSect->Strict.uEnterId     = uId;
    350     ASMAtomicWriteHandle(&pCritSect->Strict.ThreadOwner, ThreadSelf);
     341    RTLockValidatorSetOwner(pCritSect->pValidatorRec, ThreadSelf, uId, RT_SRC_POS_ARGS);
    351342    RTThreadWriteLockInc(ThreadSelf);
    352343#endif
     
    354345    return VINF_SUCCESS;
    355346}
     347#ifdef RTCRITSECT_STRICT
     348RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
     349#else
    356350RT_EXPORT_SYMBOL(RTCritSectEnter);
    357 
    358 
    359 /**
    360  * Leave a critical section.
    361  *
    362  * @returns VINF_SUCCESS.
    363  * @param   pCritSect   The critical section.
    364  */
     351#endif
     352
     353
     354#ifdef RTCRITSECT_STRICT
     355RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
     356{
     357    return RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS);
     358}
     359RT_EXPORT_SYMBOL(RTCritSectEnter);
     360
     361
     362#else  /* !RTCRITSECT_STRICT */
     363RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     364{
     365    return RTCritSectEnter(pCritSect);
     366}
     367RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
     368#endif /* !RTCRITSECT_STRICT */
     369
     370
    365371RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect)
    366372{
     
    387393         */
    388394#ifdef RTCRITSECT_STRICT
    389         if (pCritSect->Strict.ThreadOwner != NIL_RTTHREAD) /* May happen for PDMCritSects when entering GC/R0. */
    390             RTThreadWriteLockDec(pCritSect->Strict.ThreadOwner);
    391         ASMAtomicWriteHandle(&pCritSect->Strict.ThreadOwner, NIL_RTTHREAD);
     395        RTLockValidatorUnsetOwner(pCritSect->pValidatorRec);
    392396#endif
    393397        ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NIL_RTNATIVETHREAD);
     
    403407
    404408
    405 /**
    406  * Leave multiple critical sections.
    407  *
    408  * @returns VINF_SUCCESS.
    409  * @param   cCritSects      Number of critical sections in the array.
    410  * @param   papCritSects    Array of critical section pointers.
    411  */
    412 RTDECL(int) RTCritSectLeaveMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects)
     409RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
    413410{
    414411    int rc = VINF_SUCCESS;
    415     for (unsigned i = 0; i < cCritSects; i++)
     412    for (size_t i = 0; i < cCritSects; i++)
    416413    {
    417414        int rc2 = RTCritSectLeave(papCritSects[i]);
     
    424421
    425422
    426 #ifndef RTCRITSECT_STRICT
    427 RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    428 {
    429     return RTCritSectEnter(pCritSect);
    430 }
    431 
    432 RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    433 {
    434     return RTCritSectTryEnter(pCritSect);
    435 }
    436 
    437 RTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    438 {
    439     return RTCritSectEnterMultiple(cCritSects, papCritSects);
    440 }
    441 #endif /* RT_STRICT */
    442 RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
    443 RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
    444 RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
    445 
    446 
    447 /**
    448  * Deletes a critical section.
    449  *
    450  * @returns VINF_SUCCESS.
    451  * @param   pCritSect   The critical section.
    452  */
    453423RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect)
    454424{
     
    472442    RTSEMEVENT EventSem = pCritSect->EventSem;
    473443    pCritSect->EventSem         = NIL_RTSEMEVENT;
     444
    474445    while (pCritSect->cLockers-- >= 0)
    475446        RTSemEventSignal(EventSem);
     
    478449    AssertRC(rc);
    479450
     451    RTLockValidatorDestroy(&pCritSect->pValidatorRec);
     452
    480453    return rc;
    481454}
  • trunk/src/VBox/Runtime/include/internal/magics.h

    r25059 r25368  
    6767/** The magic value for RTLOCALIPCSERVER::u32Magic. (Katsuhiro Otomo) */
    6868#define RTLOCALIPCSESSION_MAGIC     0x19530414
     69/** The magic value for RTLOCKVALIDATORREC::u32Magic. (Vladimir Vladimirovich Nabokov) */
     70#define RTLOCKVALIDATORREC_MAGIC    0x18990422
     71/** The dead magic value for RTLOCKVALIDATORREC::u32Magic. */
     72#define RTLOCKVALIDATORREC_MAGIC_DEAD 0x19770702
    6973/** Magic number for RTMEMCACHEINT::u32Magic. (Joseph Weizenbaum) */
    7074#define RTMEMCACHE_MAGIC            0x19230108
  • trunk/src/VBox/Runtime/include/internal/thread.h

    r23124 r25368  
    9393    union RTTHREADINTBLOCKID
    9494    {
     95        PRTLOCKVALIDATORREC pRec;
    9596        uint64_t            u64;
    96         PRTCRITSECT         pCritSect;
    97         RTSEMEVENT          Event;
    98         RTSEMEVENTMULTI     EventMulti;
    99         RTSEMMUTEX          Mutex;
    10097    } Block;
    10198    /** Where we're blocking. */
     99    const char volatile    *pszBlockFunction;
     100    /** Where we're blocking. */
    102101    const char volatile    *pszBlockFile;
    103102    /** Where we're blocking. */
    104     unsigned volatile       uBlockLine;
    105     /** Where we're blocking. */
    106     RTUINTPTR volatile      uBlockId;
     103    uint32_t volatile       uBlockLine;
     104    /** Where we're blocking. */
     105    RTHCUINTPTR volatile    uBlockId;
    107106    /** Number of registered write locks, mutexes and critsects that this thread owns. */
    108107    int32_t volatile        cWriteLocks;
  • trunk/src/VBox/Runtime/testcase/tstDeadlock.cpp

    r14831 r25368  
    3333*   Header Files                                                               *
    3434*******************************************************************************/
    35 #include <iprt/thread.h>
     35#include <iprt/asm.h>                   /* for return addresses */
    3636#include <iprt/critsect.h>
    37 #include <iprt/stream.h>
     37
    3838#include <iprt/err.h>
    3939#include <iprt/initterm.h>
     40#include <iprt/stream.h>
     41#include <iprt/thread.h>
    4042
    4143
     
    7880    RTPrintf("thread3: taking 1\n");
    7981    RTCritSectEnter(&g_CritSect1);
    80     RTPrintf("thread1: got 1!!!\n");
     82    RTPrintf("thread3: got 1!!!\n");
    8183    return VERR_DEADLOCK;
    8284}
     
    100102    }
    101103    RTCritSectEnter(&g_CritSect1);
    102     if (g_CritSect1.Strict.ThreadOwner == NIL_RTTHREAD)
     104    if (!g_CritSect1.pValidatorRec || g_CritSect1.pValidatorRec->hThread == NIL_RTTHREAD)
    103105    {
    104106        RTPrintf("tstDeadlock: deadlock detection is not enabled in this build\n");
  • trunk/src/VBox/VMM/PDMCritSect.cpp

    r23350 r25368  
    126126    if (RT_SUCCESS(rc))
    127127    {
    128         /*
    129          * Initialize the structure (first bit is c&p from RTCritSectInitEx).
    130          */
    131         pCritSect->Core.u32Magic             = RTCRITSECT_MAGIC;
    132         pCritSect->Core.fFlags               = 0;
    133         pCritSect->Core.cNestings            = 0;
    134         pCritSect->Core.cLockers             = -1;
    135         pCritSect->Core.NativeThreadOwner    = NIL_RTNATIVETHREAD;
    136         pCritSect->Core.Strict.ThreadOwner   = NIL_RTTHREAD;
    137         pCritSect->Core.Strict.pszEnterFile  = NULL;
    138         pCritSect->Core.Strict.u32EnterLine  = 0;
    139         pCritSect->Core.Strict.uEnterId      = 0;
    140         pCritSect->pVMR3                     = pVM;
    141         pCritSect->pVMR0                     = pVM->pVMR0;
    142         pCritSect->pVMRC                     = pVM->pVMRC;
    143         pCritSect->pvKey                     = pvKey;
    144         pCritSect->EventToSignal             = NIL_RTSEMEVENT;
    145         pCritSect->pNext                     = pVM->pdm.s.pCritSects;
    146         pCritSect->pszName                   = RTStrDup(pszName);
    147         pVM->pdm.s.pCritSects = pCritSect;
    148         STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLock,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZLock", pszName);
    149         STAMR3RegisterF(pVM, &pCritSect->StatContentionRZUnlock,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZUnlock", pszName);
    150         STAMR3RegisterF(pVM, &pCritSect->StatContentionR3,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionR3", pszName);
     128        rc = RTLockValidatorCreate(&pCritSect->Core.pValidatorRec, NIL_RTLOCKVALIDATORCLASS, 0, pszName, pCritSect);
     129        if (RT_SUCCESS(rc))
     130        {
     131            /*
     132             * Initialize the structure (first bit is c&p from RTCritSectInitEx).
     133             */
     134            pCritSect->Core.u32Magic             = RTCRITSECT_MAGIC;
     135            pCritSect->Core.fFlags               = 0;
     136            pCritSect->Core.cNestings            = 0;
     137            pCritSect->Core.cLockers             = -1;
     138            pCritSect->Core.NativeThreadOwner    = NIL_RTNATIVETHREAD;
     139            pCritSect->pVMR3                     = pVM;
     140            pCritSect->pVMR0                     = pVM->pVMR0;
     141            pCritSect->pVMRC                     = pVM->pVMRC;
     142            pCritSect->pvKey                     = pvKey;
     143            pCritSect->EventToSignal             = NIL_RTSEMEVENT;
     144            pCritSect->pNext                     = pVM->pdm.s.pCritSects;
     145            pCritSect->pszName                   = RTStrDup(pszName);
     146            pVM->pdm.s.pCritSects = pCritSect;
     147            STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLock,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZLock", pszName);
     148            STAMR3RegisterF(pVM, &pCritSect->StatContentionRZUnlock,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZUnlock", pszName);
     149            STAMR3RegisterF(pVM, &pCritSect->StatContentionR3,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionR3", pszName);
    151150#ifdef VBOX_WITH_STATISTICS
    152         STAMR3RegisterF(pVM, &pCritSect->StatLocked,        STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSects/%s/Locked", pszName);
     151            STAMR3RegisterF(pVM, &pCritSect->StatLocked,        STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSects/%s/Locked", pszName);
    153152#endif
     153            return VINF_SUCCESS;
     154        }
     155
     156        SUPSemEventClose(pVM->pSession, (SUPSEMEVENT)pCritSect->Core.EventSem);
    154157    }
    155158    return rc;
     
    241244    int rc = SUPSemEventClose(pVM->pSession, hEvent);
    242245    AssertRC(rc);
     246    RTLockValidatorDestroy(&pCritSect->Core.pValidatorRec);
    243247    pCritSect->pNext   = NULL;
    244248    pCritSect->pvKey   = NULL;
     
    390394        return false;
    391395
     396#ifdef PDMCRITSECT_STRICT
     397    const char * const pszFile      = pCritSect->s.Core.pValidatorRec->pszFile;
     398    const char * const pszFunction  = pCritSect->s.Core.pValidatorRec->pszFunction;
     399    uint32_t     const iLine        = pCritSect->s.Core.pValidatorRec->uLine;
     400    RTHCUINTPTR  const uId          = pCritSect->s.Core.pValidatorRec->uId;
     401#endif
    392402    PDMCritSectLeave(pCritSect);
    393403
     
    411421    }
    412422
     423#ifdef PDMCRITSECT_STRICT
     424    int rc = PDMCritSectEnterDebug(pCritSect, VERR_INTERNAL_ERROR, uId, pszFile, iLine, pszFunction);
     425#else
    413426    int rc = PDMCritSectEnter(pCritSect, VERR_INTERNAL_ERROR);
     427#endif
    414428    AssertLogRelRC(rc);
    415429    return true;
  • trunk/src/VBox/VMM/PDMInternal.h

    r24744 r25368  
    4949#if defined(DOXYGEN_RUNNING) || 1
    5050# define PDM_WITH_R3R0_CRIT_SECT
     51#endif
     52
     53/** @def PDMCRITSECT_STRICT
     54 * Enables/disables PDM critsect strictness like deadlock detection. */
     55#if defined(VBOX_STRICT) || defined(DOXYGEN_RUNNING)
     56# define PDMCRITSECT_STRICT
    5157#endif
    5258
  • trunk/src/VBox/VMM/REMInternal.h

    r22707 r25368  
    217217    STAMPROFILE             StatsStateBack;
    218218
    219     /** Padding the CPUX86State structure to 32 byte. */
    220     uint32_t                abPadding[HC_ARCH_BITS == 32 ? 2 : 6];
     219    /** Padding the CPUX86State structure to 64 byte. */
     220    uint32_t                abPadding[HC_ARCH_BITS == 32 ? 4 : 4];
    221221
    222222# define REM_ENV_SIZE       0xff00
  • trunk/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp

    r23350 r25368  
    5151#define PDMCRITSECT_SPIN_COUNT_RC       256
    5252
    53 /** @def PDMCRITSECT_STRICT
    54  * Enables/disables PDM critsect strictness like deadlock detection. */
    55 #if defined(VBOX_STRICT) || defined(DOXYGEN_RUNNING)
    56 # define PDMCRITSECT_STRICT
    57 #endif
     53#ifdef PDMCRITSECT_STRICT
     54# define PDMCRITSECT_STRICT_ARGS_DECL       RTHCUINTPTR uId, RT_SRC_POS_DECL
     55# define PDMCRITSECT_STRICT_ARGS_PASS_ON    uId, RT_SRC_POS_ARGS
     56#else
     57# define PDMCRITSECT_STRICT_ARGS_DECL       int iDummy
     58# define PDMCRITSECT_STRICT_ARGS_PASS_ON    0
     59#endif
     60
     61
     62/* Undefine the automatic VBOX_STRICT API mappings. */
     63#undef PDMCritSectEnter
     64#undef PDMCritSectTryEnter
    5865
    5966
     
    8895 * @param   hNativeSelf     The native handle of this thread.
    8996 */
    90 DECL_FORCE_INLINE(int) pdmCritSectEnterFirst(PPDMCRITSECT pCritSect, RTNATIVETHREAD hNativeSelf)
     97DECL_FORCE_INLINE(int) pdmCritSectEnterFirst(PPDMCRITSECT pCritSect, RTNATIVETHREAD hNativeSelf, PDMCRITSECT_STRICT_ARGS_DECL)
    9198{
    9299    AssertMsg(pCritSect->s.Core.NativeThreadOwner == NIL_RTNATIVETHREAD, ("NativeThreadOwner=%p\n", pCritSect->s.Core.NativeThreadOwner));
     
    97104
    98105# if defined(PDMCRITSECT_STRICT) && defined(IN_RING3)
    99     pCritSect->s.Core.Strict.pszEnterFile = NULL;
    100     pCritSect->s.Core.Strict.u32EnterLine = 0;
    101     pCritSect->s.Core.Strict.uEnterId     = 0;
    102     RTTHREAD hSelf = RTThreadSelf();
    103     ASMAtomicWriteHandle(&pCritSect->s.Core.Strict.ThreadOwner, hSelf);
    104     RTThreadWriteLockInc(hSelf);
     106    RTLockValidatorSetOwner(pCritSect->s.Core.pValidatorRec, NIL_RTTHREAD, PDMCRITSECT_STRICT_ARGS_PASS_ON);
     107    RTThreadWriteLockInc(pCritSect->s.Core.pValidatorRec->hThread);
    105108# endif
    106109
     
    118121 * @param   hNativeSelf         The native thread handle.
    119122 */
    120 static int pdmR3CritSectEnterContended(PPDMCRITSECT pCritSect, RTNATIVETHREAD hNativeSelf)
     123static int pdmR3CritSectEnterContended(PPDMCRITSECT pCritSect, RTNATIVETHREAD hNativeSelf, PDMCRITSECT_STRICT_ARGS_DECL)
    121124{
    122125    /*
     
    124127     */
    125128    if (ASMAtomicIncS32(&pCritSect->s.Core.cLockers) == 0)
    126         return pdmCritSectEnterFirst(pCritSect, hNativeSelf);
     129        return pdmCritSectEnterFirst(pCritSect, hNativeSelf, PDMCRITSECT_STRICT_ARGS_PASS_ON);
    127130    STAM_COUNTER_INC(&pCritSect->s.StatContentionR3);
    128131
     
    136139    if (hSelf == NIL_RTTHREAD)
    137140        RTThreadAdopt(RTTHREADTYPE_DEFAULT, 0, NULL, &hSelf);
     141    RTLockValidatorCheckOrder(pCritSect->s.Core.pValidatorRec, hSelf, 0, NULL, 0, NULL);
    138142# endif
    139143    for (;;)
    140144    {
    141145# ifdef PDMCRITSECT_STRICT
    142         RTThreadBlocking(hSelf, RTTHREADSTATE_CRITSECT, (uintptr_t)pCritSect, NULL, 0, 0);
     146        RTThreadBlocking(hSelf, RTTHREADSTATE_CRITSECT, pCritSect->s.Core.pValidatorRec, 0, NULL, 0, NULL);
    143147# endif
    144148        int rc = SUPSemEventWaitNoResume(pSession, hEvent, RT_INDEFINITE_WAIT);
     
    149153            return VERR_SEM_DESTROYED;
    150154        if (rc == VINF_SUCCESS)
    151             return pdmCritSectEnterFirst(pCritSect, hNativeSelf);
     155            return pdmCritSectEnterFirst(pCritSect, hNativeSelf, PDMCRITSECT_STRICT_ARGS_PASS_ON);
    152156        AssertMsg(rc == VERR_INTERRUPTED, ("rc=%Rrc\n", rc));
    153157    }
     
    158162
    159163/**
    160  * Enters a PDM critical section.
     164 * Common worker for the debug and normal APIs.
    161165 *
    162166 * @returns VINF_SUCCESS if entered successfully.
     
    168172 *                              and the section is busy.
    169173 */
    170 VMMDECL(int) PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy)
     174DECL_FORCE_INLINE(int) pdmCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy, PDMCRITSECT_STRICT_ARGS_DECL)
    171175{
    172176    Assert(pCritSect->s.Core.cNestings < 8);  /* useful to catch incorrect locking */
     
    185189    /* Not owned ... */
    186190    if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
    187         return pdmCritSectEnterFirst(pCritSect, hNativeSelf);
     191        return pdmCritSectEnterFirst(pCritSect, hNativeSelf, PDMCRITSECT_STRICT_ARGS_PASS_ON);
    188192
    189193    /* ... or nested. */
     
    205209    {
    206210        if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
    207             return pdmCritSectEnterFirst(pCritSect, hNativeSelf);
     211            return pdmCritSectEnterFirst(pCritSect, hNativeSelf, PDMCRITSECT_STRICT_ARGS_PASS_ON);
    208212        ASMNopPause();
    209213        /** @todo Should use monitor/mwait on e.g. &cLockers here, possibly with a
     
    218222     * Take the slow path.
    219223     */
    220     return pdmR3CritSectEnterContended(pCritSect, hNativeSelf);
     224    return pdmR3CritSectEnterContended(pCritSect, hNativeSelf, PDMCRITSECT_STRICT_ARGS_PASS_ON);
    221225#else
    222226    /*
     
    231235
    232236/**
    233  * Try enter a critical section.
     237 * Enters a PDM critical section.
     238 *
     239 * @returns VINF_SUCCESS if entered successfully.
     240 * @returns rcBusy when encountering a busy critical section in GC/R0.
     241 * @returns VERR_SEM_DESTROYED if the critical section is dead.
     242 *
     243 * @param   pCritSect           The PDM critical section to enter.
     244 * @param   rcBusy              The status code to return when we're in GC or R0
     245 *                              and the section is busy.
     246 */
     247VMMDECL(int) PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy)
     248{
     249#ifndef PDMCRITSECT_STRICT
     250    return pdmCritSectEnter(pCritSect, rcBusy, PDMCRITSECT_STRICT_ARGS_PASS_ON);
     251#else
     252    /* No need for a second code instance. */
     253    return PDMCritSectEnterDebug(pCritSect, rcBusy, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
     254#endif
     255}
     256
     257
     258/**
     259 * Enters a PDM critical section, with location information for debugging.
     260 *
     261 * @returns VINF_SUCCESS if entered successfully.
     262 * @returns rcBusy when encountering a busy critical section in GC/R0.
     263 * @returns VERR_SEM_DESTROYED if the critical section is dead.
     264 *
     265 * @param   pCritSect           The PDM critical section to enter.
     266 * @param   rcBusy              The status code to return when we're in GC or R0
     267 *                              and the section is busy.
     268 * @param   uId                 Some kind of locking location ID.  Typically a
     269 *                              return address up the stack.  Optional (0).
     270 * @param   pszFile             The file where the lock is being acquired from.
     271 *                              Optional.
     272 * @param   iLine               The line number in that file.  Optional (0).
     273 * @param   pszFunction         The functionn where the lock is being acquired
     274 *                              from.  Optional.
     275 */
     276VMMDECL(int) PDMCritSectEnterDebug(PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     277{
     278#ifdef PDMCRITSECT_STRICT
     279    return pdmCritSectEnter(pCritSect, rcBusy, PDMCRITSECT_STRICT_ARGS_PASS_ON);
     280#else
     281    /* No need for a second code instance. */
     282    return PDMCritSectEnter(pCritSect, rcBusy);
     283#endif
     284}
     285
     286
     287/**
     288 * Common worker for the debug and normal APIs.
    234289 *
    235290 * @retval  VINF_SUCCESS on success.
     
    240295 * @param   pCritSect   The critical section.
    241296 */
    242 VMMDECL(int) PDMCritSectTryEnter(PPDMCRITSECT pCritSect)
     297static int pdmCritSectTryEnter(PPDMCRITSECT pCritSect, PDMCRITSECT_STRICT_ARGS_DECL)
    243298{
    244299    /*
     
    255310    /* Not owned ... */
    256311    if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
    257         return pdmCritSectEnterFirst(pCritSect, hNativeSelf);
     312        return pdmCritSectEnterFirst(pCritSect, hNativeSelf, PDMCRITSECT_STRICT_ARGS_PASS_ON);
    258313
    259314    /* ... or nested. */
     
    281336
    282337
     338/**
     339 * Try enter a critical section.
     340 *
     341 * @retval  VINF_SUCCESS on success.
     342 * @retval  VERR_SEM_BUSY if the critsect was owned.
     343 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     344 * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     345 *
     346 * @param   pCritSect   The critical section.
     347 */
     348VMMDECL(int) PDMCritSectTryEnter(PPDMCRITSECT pCritSect)
     349{
     350#ifndef PDMCRITSECT_STRICT
     351    return pdmCritSectTryEnter(pCritSect, PDMCRITSECT_STRICT_ARGS_PASS_ON);
     352#else
     353    /* No need for a second code instance. */
     354    return PDMCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
     355#endif
     356}
     357
     358
     359/**
     360 * Try enter a critical section, with location information for debugging.
     361 *
     362 * @retval  VINF_SUCCESS on success.
     363 * @retval  VERR_SEM_BUSY if the critsect was owned.
     364 * @retval  VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
     365 * @retval  VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
     366 *
     367 * @param   pCritSect           The critical section.
     368 * @param   uId                 Some kind of locking location ID.  Typically a
     369 *                              return address up the stack.  Optional (0).
     370 * @param   pszFile             The file where the lock is being acquired from.
     371 *                              Optional.
     372 * @param   iLine               The line number in that file.  Optional (0).
     373 * @param   pszFunction         The functionn where the lock is being acquired
     374 *                              from.  Optional.
     375 */
     376VMMDECL(int) PDMCritSectTryEnterDebug(PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     377{
     378#ifdef PDMCRITSECT_STRICT
     379    return pdmCritSectTryEnter(pCritSect, PDMCRITSECT_STRICT_ARGS_PASS_ON);
     380#else
     381    /* No need for a second code instance. */
     382    return PDMCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
     383#endif
     384}
     385
     386
    283387#ifdef IN_RING3
    284388/**
     
    297401    if (    rc == VINF_SUCCESS
    298402        &&  fCallRing3
    299         &&  pCritSect->s.Core.Strict.ThreadOwner != NIL_RTTHREAD)
    300     {
    301         RTThreadWriteLockDec(pCritSect->s.Core.Strict.ThreadOwner);
    302         ASMAtomicWriteHandle(&pCritSect->s.Core.Strict.ThreadOwner, NIL_RTTHREAD);
     403        &&  pCritSect->s.Core.pValidatorRec
     404        &&  pCritSect->s.Core.pValidatorRec->hThread != NIL_RTTHREAD)
     405    {
     406        RTThreadWriteLockDec(pCritSect->s.Core.pValidatorRec->hThread);
     407        RTLockValidatorUnsetOwner(pCritSect->s.Core.pValidatorRec);
    303408    }
    304409    return rc;
     
    346451        pCritSect->s.EventToSignal   = NIL_RTSEMEVENT;
    347452#  if defined(PDMCRITSECT_STRICT)
    348         if (pCritSect->s.Core.Strict.ThreadOwner != NIL_RTTHREAD)
    349             RTThreadWriteLockDec(pCritSect->s.Core.Strict.ThreadOwner);
    350         ASMAtomicWriteHandle(&pCritSect->s.Core.Strict.ThreadOwner, NIL_RTTHREAD);
     453        if (pCritSect->s.Core.pValidatorRec->hThread != NIL_RTTHREAD)
     454        {
     455            RTThreadWriteLockDec(pCritSect->s.Core.pValidatorRec->hThread);
     456            RTLockValidatorUnsetOwner(pCritSect->s.Core.pValidatorRec);
     457        }
    351458#  endif
    352459# endif
    353460        ASMAtomicAndU32(&pCritSect->s.Core.fFlags, ~PDMCRITSECT_FLAGS_PENDING_UNLOCK);
    354         Assert(pCritSect->s.Core.Strict.ThreadOwner == NIL_RTTHREAD);
     461        Assert(!pCritSect->s.Core.pValidatorRec || pCritSect->s.Core.pValidatorRec->hThread == NIL_RTTHREAD);
    355462        ASMAtomicWriteHandle(&pCritSect->s.Core.NativeThreadOwner, NIL_RTNATIVETHREAD);
    356463        ASMAtomicDecS32(&pCritSect->s.Core.cNestings);
  • trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp

    r22890 r25368  
    406406
    407407    /*
    408      * Don't make updates untill
     408     * Don't make updates until we've check the timer qeueue.
    409409     */
    410410    bool            fUpdatePrev = true;
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r24730 r25368  
    976976    GEN_CHECK_OFF(RTCRITSECT, fFlags);
    977977    GEN_CHECK_OFF(RTCRITSECT, EventSem);
    978     GEN_CHECK_OFF(RTCRITSECT, Strict.ThreadOwner);
    979     GEN_CHECK_OFF(RTCRITSECT, Strict.pszEnterFile);
    980     GEN_CHECK_OFF(RTCRITSECT, Strict.u32EnterLine);
    981     GEN_CHECK_OFF(RTCRITSECT, Strict.uEnterId);
    982 
     978    GEN_CHECK_OFF(RTCRITSECT, pValidatorRec);
    983979
    984980    GEN_CHECK_SIZE(CSAM);
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r23366 r25368  
    249249    CHECK_MEMBER_ALIGNMENT(VM, rem.s.uPendingExcptCR2, 8);
    250250    CHECK_MEMBER_ALIGNMENT(VM, rem.s.StatsInQEMU, 8);
    251     CHECK_MEMBER_ALIGNMENT(VM, rem.s.Env, 32);
     251    CHECK_MEMBER_ALIGNMENT(VM, rem.s.Env, 64);
    252252
    253253    /* the VMCPUs are page aligned TLB hit reassons. */
Note: See TracChangeset for help on using the changeset viewer.

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