VirtualBox

Changeset 25368 in vbox for trunk/include/iprt


Ignore:
Timestamp:
Dec 14, 2009 4:31:40 PM (15 years ago)
Author:
vboxsync
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/include/iprt
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • 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/**
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