2 * IPRT - Lock Validator.
6 * Copyright (C) 2009-2017 Oracle Corporation
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
26 #ifndef ___iprt_lockvalidator_h
27 #define ___iprt_lockvalidator_h
29 #include <iprt/cdefs.h>
30 #include <iprt/types.h>
31 #include <iprt/assert.h>
32 #include <iprt/thread.h>
33 #include <iprt/stdarg.h>
36 /** @defgroup grp_rtlockval RTLockValidator - Lock Validator
43 /** Pointer to a record union.
45 typedef union RTLOCKVALRECUNION
*PRTLOCKVALRECUNION
;
50 typedef struct RTLOCKVALSRCPOS
52 /** The file where the lock was taken. */
53 R3R0PTRTYPE(const char * volatile) pszFile
;
54 /** The function where the lock was taken. */
55 R3R0PTRTYPE(const char * volatile) pszFunction
;
56 /** Some ID indicating where the lock was taken, typically an address. */
57 RTHCUINTPTR
volatile uId
;
58 /** The line number in the file. */
59 uint32_t volatile uLine
;
60 #if HC_ARCH_BITS == 64
61 uint32_t u32Padding
; /**< Alignment padding. */
64 AssertCompileSize(RTLOCKVALSRCPOS
, HC_ARCH_BITS
== 32 ? 16 : 32);
65 /* The pointer types are defined in iprt/types.h. */
67 /** @def RTLOCKVALSRCPOS_INIT
68 * Initializer for a RTLOCKVALSRCPOS variable.
70 * @param pszFile The file name. Optional (NULL).
71 * @param uLine The line number in that file. Optional (0).
72 * @param pszFunction The function. Optional (NULL).
73 * @param uId Some location ID, normally the return address.
76 #if HC_ARCH_BITS == 64
77 # define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \
78 { (pszFile), (pszFunction), (uId), (uLine), 0 }
80 # define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \
81 { (pszFile), (pszFunction), (uId), (uLine) }
84 /** @def RTLOCKVALSRCPOS_INIT_DEBUG_API
85 * Initializer for a RTLOCKVALSRCPOS variable in a typicial debug API
86 * variant. Assumes RT_SRC_POS_DECL and RTHCUINTPTR uId as arguments.
88 #define RTLOCKVALSRCPOS_INIT_DEBUG_API() \
89 RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, uId)
91 /** @def RTLOCKVALSRCPOS_INIT_NORMAL_API
92 * Initializer for a RTLOCKVALSRCPOS variable in a normal API
93 * variant. Assumes iprt/asm.h is included.
95 #define RTLOCKVALSRCPOS_INIT_NORMAL_API() \
96 RTLOCKVALSRCPOS_INIT(__FILE__, __LINE__, __PRETTY_FUNCTION__, (uintptr_t)ASMReturnAddress())
98 /** @def RTLOCKVALSRCPOS_INIT_POS_NO_ID
99 * Initializer for a RTLOCKVALSRCPOS variable when no @c uId is present.
100 * Assumes iprt/asm.h is included.
102 #define RTLOCKVALSRCPOS_INIT_POS_NO_ID() \
103 RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, (uintptr_t)ASMReturnAddress())
107 * Lock validator record core.
109 typedef struct RTLOCKVALRECORE
111 /** The magic value indicating the record type. */
112 uint32_t volatile u32Magic
;
114 /** Pointer to a lock validator record core. */
115 typedef RTLOCKVALRECCORE
*PRTLOCKVALRECCORE
;
116 /** Pointer to a const lock validator record core. */
117 typedef RTLOCKVALRECCORE
const *PCRTLOCKVALRECCORE
;
121 * Record recording the exclusive ownership of a lock.
123 * This is typically part of the per-lock data structure when compiling with
124 * the lock validator.
126 typedef struct RTLOCKVALRECEXCL
128 /** Record core with RTLOCKVALRECEXCL_MAGIC as the magic value. */
129 RTLOCKVALRECCORE Core
;
130 /** Whether it's enabled or not. */
134 /** Source position where the lock was taken. */
135 RTLOCKVALSRCPOS SrcPos
;
136 /** The current owner thread. */
137 RTTHREAD
volatile hThread
;
138 /** Pointer to the lock record below us. Only accessed by the owner. */
139 R3R0PTRTYPE(PRTLOCKVALRECUNION
) pDown
;
140 /** Recursion count */
142 /** The lock sub-class. */
143 uint32_t volatile uSubClass
;
144 /** The lock class. */
145 RTLOCKVALCLASS hClass
;
146 /** Pointer to the lock. */
148 /** Pointer to the next sibling record.
149 * This is used to find the read side of a read-write lock. */
150 R3R0PTRTYPE(PRTLOCKVALRECUNION
) pSibling
;
152 * @remarks The bytes beyond 32 are for better size alignment and can be
153 * taken and used for other purposes if it becomes necessary. */
154 char szName
[32 + (HC_ARCH_BITS
== 32 ? 12 : 8)];
156 AssertCompileSize(RTLOCKVALRECEXCL
, HC_ARCH_BITS
== 32 ? 0x60 : 0x80);
157 /* The pointer type is defined in iprt/types.h. */
160 * For recording the one ownership share.
162 typedef struct RTLOCKVALRECSHRDOWN
164 /** Record core with RTLOCKVALRECSHRDOWN_MAGIC as the magic value. */
165 RTLOCKVALRECCORE Core
;
166 /** Recursion count */
168 /** Static (true) or dynamic (false) allocated record. */
172 /** The current owner thread. */
173 RTTHREAD
volatile hThread
;
174 /** Pointer to the lock record below us. Only accessed by the owner. */
175 R3R0PTRTYPE(PRTLOCKVALRECUNION
) pDown
;
176 /** Pointer back to the shared record. */
177 R3R0PTRTYPE(PRTLOCKVALRECSHRD
) pSharedRec
;
178 #if HC_ARCH_BITS == 32
182 /** Source position where the lock was taken. */
183 RTLOCKVALSRCPOS SrcPos
;
184 } RTLOCKVALRECSHRDOWN
;
185 AssertCompileSize(RTLOCKVALRECSHRDOWN
, HC_ARCH_BITS
== 32 ? 24 + 16 : 32 + 32);
186 /** Pointer to a RTLOCKVALRECSHRDOWN. */
187 typedef RTLOCKVALRECSHRDOWN
*PRTLOCKVALRECSHRDOWN
;
190 * Record recording the shared ownership of a lock.
192 * This is typically part of the per-lock data structure when compiling with
193 * the lock validator.
195 typedef struct RTLOCKVALRECSHRD
197 /** Record core with RTLOCKVALRECSHRD_MAGIC as the magic value. */
198 RTLOCKVALRECCORE Core
;
199 /** The lock sub-class. */
200 uint32_t volatile uSubClass
;
201 /** The lock class. */
202 RTLOCKVALCLASS hClass
;
203 /** Pointer to the lock. */
205 /** Pointer to the next sibling record.
206 * This is used to find the write side of a read-write lock. */
207 R3R0PTRTYPE(PRTLOCKVALRECUNION
) pSibling
;
209 /** The number of entries in the table.
210 * Updated before inserting and after removal. */
211 uint32_t volatile cEntries
;
212 /** The index of the last entry (approximately). */
213 uint32_t volatile iLastEntry
;
214 /** The max table size. */
215 uint32_t volatile cAllocated
;
216 /** Set if the table is being reallocated, clear if not.
217 * This is used together with rtLockValidatorSerializeDetectionEnter to make
218 * sure there is exactly one thread doing the reallocation and that nobody is
219 * using the table at that point. */
220 bool volatile fReallocating
;
221 /** Whether it's enabled or not. */
223 /** Set if event semaphore signaller, clear if read-write semaphore. */
225 /** Alignment padding. */
227 /** Pointer to a table containing pointers to records of all the owners. */
228 R3R0PTRTYPE(PRTLOCKVALRECSHRDOWN
volatile *) papOwners
;
231 * @remarks The bytes beyond 32 are for better size alignment and can be
232 * taken and used for other purposes if it becomes necessary. */
233 char szName
[32 + (HC_ARCH_BITS
== 32 ? 8 : 8)];
235 AssertCompileSize(RTLOCKVALRECSHRD
, HC_ARCH_BITS
== 32 ? 0x50 : 0x60);
239 * Makes the two records siblings.
241 * @returns VINF_SUCCESS on success, VERR_SEM_LV_INVALID_PARAMETER if either of
242 * the records are invalid.
243 * @param pRec1 Record 1.
244 * @param pRec2 Record 2.
246 RTDECL(int) RTLockValidatorRecMakeSiblings(PRTLOCKVALRECCORE pRec1
, PRTLOCKVALRECCORE pRec2
);
249 * Initialize a lock validator record.
251 * Use RTLockValidatorRecExclDelete to deinitialize it.
253 * @param pRec The record.
254 * @param hClass The class (no reference consumed). If NIL, the
255 * no lock order validation will be performed on
257 * @param uSubClass The sub-class. This is used to define lock
258 * order inside the same class. If you don't know,
259 * then pass RTLOCKVAL_SUB_CLASS_NONE.
260 * @param hLock The lock handle.
261 * @param fEnabled Pass @c false to explicitly disable lock
262 * validation, otherwise @c true.
263 * @param pszNameFmt Name format string for the lock validator,
264 * optional (NULL). Max length is 32 bytes.
265 * @param ... Format string arguments.
267 RTDECL(void) RTLockValidatorRecExclInit(PRTLOCKVALRECEXCL pRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
, void *hLock
,
268 bool fEnabled
, const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
270 * Initialize a lock validator record.
272 * Use RTLockValidatorRecExclDelete to deinitialize it.
274 * @param pRec The record.
275 * @param hClass The class (no reference consumed). If NIL, the
276 * no lock order validation will be performed on
278 * @param uSubClass The sub-class. This is used to define lock
279 * order inside the same class. If you don't know,
280 * then pass RTLOCKVAL_SUB_CLASS_NONE.
281 * @param hLock The lock handle.
282 * @param fEnabled Pass @c false to explicitly disable lock
283 * validation, otherwise @c true.
284 * @param pszNameFmt Name format string for the lock validator,
285 * optional (NULL). Max length is 32 bytes.
286 * @param va Format string arguments.
288 RTDECL(void) RTLockValidatorRecExclInitV(PRTLOCKVALRECEXCL pRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
, void *hLock
,
289 bool fEnabled
, const char *pszNameFmt
, va_list va
) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 0);
291 * Uninitialize a lock validator record previously initialized by
292 * RTLockRecValidatorInit.
294 * @param pRec The record. Must be valid.
296 RTDECL(void) RTLockValidatorRecExclDelete(PRTLOCKVALRECEXCL pRec
);
299 * Create and initialize a lock validator record.
301 * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned
304 * @return VINF_SUCCESS or VERR_NO_MEMORY.
305 * @param ppRec Where to return the record pointer.
306 * @param hClass The class (no reference consumed). If NIL, the
307 * no lock order validation will be performed on
309 * @param uSubClass The sub-class. This is used to define lock
310 * order inside the same class. If you don't know,
311 * then pass RTLOCKVAL_SUB_CLASS_NONE.
312 * @param hLock The lock handle.
313 * @param fEnabled Pass @c false to explicitly disable lock
314 * validation, otherwise @c true.
315 * @param pszNameFmt Name format string for the lock validator,
316 * optional (NULL). Max length is 32 bytes.
317 * @param ... Format string arguments.
319 RTDECL(int) RTLockValidatorRecExclCreate(PRTLOCKVALRECEXCL
*ppRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
, void *hLock
,
320 bool fEnabled
, const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
323 * Create and initialize a lock validator record.
325 * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned
328 * @return VINF_SUCCESS or VERR_NO_MEMORY.
329 * @param ppRec Where to return the record pointer.
330 * @param hClass The class (no reference consumed). If NIL, the
331 * no lock order validation will be performed on
333 * @param uSubClass The sub-class. This is used to define lock
334 * order inside the same class. If you don't know,
335 * then pass RTLOCKVAL_SUB_CLASS_NONE.
336 * @param hLock The lock handle.
337 * @param fEnabled Pass @c false to explicitly disable lock
338 * validation, otherwise @c true.
339 * @param pszNameFmt Name format string for the lock validator,
340 * optional (NULL). Max length is 32 bytes.
341 * @param va Format string arguments.
343 RTDECL(int) RTLockValidatorRecExclCreateV(PRTLOCKVALRECEXCL
*ppRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
, void *hLock
,
344 bool fEnabled
, const char *pszNameFmt
, va_list va
) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 0);
347 * Deinitialize and destroy a record created by RTLockValidatorRecExclCreate.
349 * @param ppRec Pointer to the record pointer. Will be set to
352 RTDECL(void) RTLockValidatorRecExclDestroy(PRTLOCKVALRECEXCL
*ppRec
);
355 * Sets the sub-class of the record.
357 * It is recommended to try make sure that nobody is using this class while
358 * changing the value.
360 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
361 * lock validator isn't compiled in or either of the parameters are
363 * @param pRec The validator record.
364 * @param uSubClass The new sub-class value.
366 RTDECL(uint32_t) RTLockValidatorRecExclSetSubClass(PRTLOCKVALRECEXCL pRec
, uint32_t uSubClass
);
369 * Record the specified thread as lock owner and increment the write lock count.
371 * This function is typically called after acquiring the lock. It accounts for
372 * recursions so it can be used instead of RTLockValidatorRecExclRecursion. Use
373 * RTLockValidatorRecExclReleaseOwner to reverse the effect.
375 * @param pRec The validator record.
376 * @param hThreadSelf The handle of the calling thread. If not known,
377 * pass NIL_RTTHREAD and we'll figure it out.
378 * @param pSrcPos The source position of the lock operation.
379 * @param fFirstRecursion Set if it is the first recursion, clear if not
382 RTDECL(void) RTLockValidatorRecExclSetOwner(PRTLOCKVALRECEXCL pRec
, RTTHREAD hThreadSelf
,
383 PCRTLOCKVALSRCPOS pSrcPos
, bool fFirstRecursion
);
386 * Check the exit order and release (unset) the ownership.
388 * This is called by routines implementing releasing an exclusive lock,
389 * typically before getting down to the final lock releasing. Can be used for
390 * recursive releasing instead of RTLockValidatorRecExclUnwind.
392 * @retval VINF_SUCCESS on success.
393 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have
394 * done all necessary whining and breakpointing before returning.
395 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
397 * @param pRec The validator record.
398 * @param fFinalRecursion Set if it's the final recursion, clear if not
401 RTDECL(int) RTLockValidatorRecExclReleaseOwner(PRTLOCKVALRECEXCL pRec
, bool fFinalRecursion
);
404 * Clear the lock ownership and decrement the write lock count.
406 * This is only for special cases where we wish to drop lock validation
407 * recording. See RTLockValidatorRecExclCheckAndRelease.
409 * @param pRec The validator record.
411 RTDECL(void) RTLockValidatorRecExclReleaseOwnerUnchecked(PRTLOCKVALRECEXCL pRec
);
414 * Checks and records a lock recursion.
416 * @retval VINF_SUCCESS on success.
417 * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone
419 * @retval VERR_SEM_LV_WRONG_ORDER if the locking order is wrong. Gone thru
421 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
423 * @param pRec The validator record.
424 * @param pSrcPos The source position of the lock operation.
426 RTDECL(int) RTLockValidatorRecExclRecursion(PRTLOCKVALRECEXCL pRec
, PCRTLOCKVALSRCPOS pSrcPos
);
429 * Checks and records a lock unwind (releasing one recursion).
431 * This should be coupled with called to RTLockValidatorRecExclRecursion.
433 * @retval VINF_SUCCESS on success.
434 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong. Gone
436 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
438 * @param pRec The validator record.
440 RTDECL(int) RTLockValidatorRecExclUnwind(PRTLOCKVALRECEXCL pRec
);
443 * Checks and records a mixed recursion.
445 * An example of a mixed recursion is a writer requesting read access to a
448 * This should be coupled with called to RTLockValidatorRecExclUnwindMixed.
450 * @retval VINF_SUCCESS on success.
451 * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone
453 * @retval VERR_SEM_LV_WRONG_ORDER if the locking order is wrong. Gone thru
455 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
457 * @param pRec The validator record it to accounted it to.
458 * @param pRecMixed The validator record it came in on.
459 * @param pSrcPos The source position of the lock operation.
461 RTDECL(int) RTLockValidatorRecExclRecursionMixed(PRTLOCKVALRECEXCL pRec
, PRTLOCKVALRECCORE pRecMixed
, PCRTLOCKVALSRCPOS pSrcPos
);
464 * Checks and records the unwinding of a mixed recursion.
466 * This should be coupled with called to RTLockValidatorRecExclRecursionMixed.
468 * @retval VINF_SUCCESS on success.
469 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong. Gone
471 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
473 * @param pRec The validator record it was accounted to.
474 * @param pRecMixed The validator record it came in on.
476 RTDECL(int) RTLockValidatorRecExclUnwindMixed(PRTLOCKVALRECEXCL pRec
, PRTLOCKVALRECCORE pRecMixed
);
479 * Check the exclusive locking order.
481 * This is called by routines implementing exclusive lock acquisition.
483 * @retval VINF_SUCCESS on success.
484 * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all
485 * necessary whining and breakpointing before returning.
486 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
488 * @param pRec The validator record.
489 * @param hThreadSelf The handle of the calling thread. If not known,
490 * pass NIL_RTTHREAD and we'll figure it out.
491 * @param pSrcPos The source position of the lock operation.
492 * @param cMillies The timeout, in milliseconds.
494 RTDECL(int) RTLockValidatorRecExclCheckOrder(PRTLOCKVALRECEXCL pRec
, RTTHREAD hThreadSelf
,
495 PCRTLOCKVALSRCPOS pSrcPos
, RTMSINTERVAL cMillies
);
498 * Do deadlock detection before blocking on exclusive access to a lock and
499 * change the thread state.
501 * @retval VINF_SUCCESS - thread is in the specified sleep state.
502 * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the
504 * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
505 * already the owner. Gone thru the motions.
506 * @retval VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock.
507 * The caller must handle any legal upgrades without invoking this
508 * function (for now).
509 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
511 * @param pRec The validator record we're blocking on.
512 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
513 * @param pSrcPos The source position of the lock operation.
514 * @param fRecursiveOk Whether it's ok to recurse.
515 * @param cMillies The timeout, in milliseconds.
516 * @param enmSleepState The sleep state to enter on successful return.
517 * @param fReallySleeping Is it really going to sleep now or not. Use
518 * false before calls to other IPRT synchronization
521 RTDECL(int) RTLockValidatorRecExclCheckBlocking(PRTLOCKVALRECEXCL pRec
, RTTHREAD hThreadSelf
,
522 PCRTLOCKVALSRCPOS pSrcPos
, bool fRecursiveOk
, RTMSINTERVAL cMillies
,
523 RTTHREADSTATE enmSleepState
, bool fReallySleeping
);
526 * RTLockValidatorRecExclCheckOrder and RTLockValidatorRecExclCheckBlocking
527 * baked into one call.
529 * @returns Any of the statuses returned by the two APIs.
530 * @param pRec The validator record.
531 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
532 * @param pSrcPos The source position of the lock operation.
533 * @param fRecursiveOk Whether it's ok to recurse.
534 * @param cMillies The timeout, in milliseconds.
535 * @param enmSleepState The sleep state to enter on successful return.
536 * @param fReallySleeping Is it really going to sleep now or not. Use
537 * false before calls to other IPRT synchronization
540 RTDECL(int) RTLockValidatorRecExclCheckOrderAndBlocking(PRTLOCKVALRECEXCL pRec
, RTTHREAD hThreadSelf
,
541 PCRTLOCKVALSRCPOS pSrcPos
, bool fRecursiveOk
, RTMSINTERVAL cMillies
,
542 RTTHREADSTATE enmSleepState
, bool fReallySleeping
);
545 * Initialize a lock validator record for a shared lock.
547 * Use RTLockValidatorRecSharedDelete to deinitialize it.
549 * @param pRec The shared lock record.
550 * @param hClass The class (no reference consumed). If NIL, the
551 * no lock order validation will be performed on
553 * @param uSubClass The sub-class. This is used to define lock
554 * order inside the same class. If you don't know,
555 * then pass RTLOCKVAL_SUB_CLASS_NONE.
556 * @param hLock The lock handle.
557 * @param fSignaller Set if event semaphore signaller logic should be
558 * applied to this record, clear if read-write
559 * semaphore logic should be used.
560 * @param fEnabled Pass @c false to explicitly disable lock
561 * validation, otherwise @c true.
562 * @param pszNameFmt Name format string for the lock validator,
563 * optional (NULL). Max length is 32 bytes.
564 * @param ... Format string arguments.
566 RTDECL(void) RTLockValidatorRecSharedInit(PRTLOCKVALRECSHRD pRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
,
567 void *hLock
, bool fSignaller
, bool fEnabled
,
568 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 8);
571 * Initialize a lock validator record for a shared lock.
573 * Use RTLockValidatorRecSharedDelete to deinitialize it.
575 * @param pRec The shared lock record.
576 * @param hClass The class (no reference consumed). If NIL, the
577 * no lock order validation will be performed on
579 * @param uSubClass The sub-class. This is used to define lock
580 * order inside the same class. If you don't know,
581 * then pass RTLOCKVAL_SUB_CLASS_NONE.
582 * @param hLock The lock handle.
583 * @param fSignaller Set if event semaphore signaller logic should be
584 * applied to this record, clear if read-write
585 * semaphore logic should be used.
586 * @param fEnabled Pass @c false to explicitly disable lock
587 * validation, otherwise @c true.
588 * @param pszNameFmt Name format string for the lock validator,
589 * optional (NULL). Max length is 32 bytes.
590 * @param va Format string arguments.
592 RTDECL(void) RTLockValidatorRecSharedInitV(PRTLOCKVALRECSHRD pRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
,
593 void *hLock
, bool fSignaller
, bool fEnabled
,
594 const char *pszNameFmt
, va_list va
) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 0);
597 * Uninitialize a lock validator record previously initialized by
598 * RTLockValidatorRecSharedInit.
600 * @param pRec The shared lock record. Must be valid.
602 RTDECL(void) RTLockValidatorRecSharedDelete(PRTLOCKVALRECSHRD pRec
);
605 * Create and initialize a lock validator record for a shared lock.
607 * Use RTLockValidatorRecSharedDestroy to deinitialize and destroy the returned
610 * @returns IPRT status code.
611 * @param ppRec Where to return the record pointer.
612 * @param hClass The class (no reference consumed). If NIL, the
613 * no lock order validation will be performed on
615 * @param uSubClass The sub-class. This is used to define lock
616 * order inside the same class. If you don't know,
617 * then pass RTLOCKVAL_SUB_CLASS_NONE.
618 * @param pvLock The lock handle or address.
619 * @param fSignaller Set if event semaphore signaller logic should be
620 * applied to this record, clear if read-write
621 * semaphore logic should be used.
622 * @param fEnabled Pass @c false to explicitly disable lock
623 * validation, otherwise @c true.
624 * @param pszNameFmt Name format string for the lock validator,
625 * optional (NULL). Max length is 32 bytes.
626 * @param ... Format string arguments.
628 RTDECL(int) RTLockValidatorRecSharedCreate(PRTLOCKVALRECSHRD
*ppRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
,
629 void *pvLock
, bool fSignaller
, bool fEnabled
,
630 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 8);
633 * Create and initialize a lock validator record for a shared lock.
635 * Use RTLockValidatorRecSharedDestroy to deinitialize and destroy the returned
638 * @returns IPRT status code.
639 * @param ppRec Where to return the record pointer.
640 * @param hClass The class (no reference consumed). If NIL, the
641 * no lock order validation will be performed on
643 * @param uSubClass The sub-class. This is used to define lock
644 * order inside the same class. If you don't know,
645 * then pass RTLOCKVAL_SUB_CLASS_NONE.
646 * @param pvLock The lock handle or address.
647 * @param fSignaller Set if event semaphore signaller logic should be
648 * applied to this record, clear if read-write
649 * semaphore logic should be used.
650 * @param fEnabled Pass @c false to explicitly disable lock
651 * validation, otherwise @c true.
652 * @param pszNameFmt Name format string for the lock validator,
653 * optional (NULL). Max length is 32 bytes.
654 * @param va Format string arguments.
656 RTDECL(int) RTLockValidatorRecSharedCreateV(PRTLOCKVALRECSHRD
*ppRec
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
,
657 void *pvLock
, bool fSignaller
, bool fEnabled
,
658 const char *pszNameFmt
, va_list va
) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(7, 0);
661 * Deinitialize and destroy a record created by RTLockValidatorRecSharedCreate.
663 * @param ppRec Pointer to the record pointer. Will be set to
666 RTDECL(void) RTLockValidatorRecSharedDestroy(PRTLOCKVALRECSHRD
*ppRec
);
669 * Sets the sub-class of the record.
671 * It is recommended to try make sure that nobody is using this class while
672 * changing the value.
674 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
675 * lock validator isn't compiled in or either of the parameters are
677 * @param pRec The validator record.
678 * @param uSubClass The new sub-class value.
680 RTDECL(uint32_t) RTLockValidatorRecSharedSetSubClass(PRTLOCKVALRECSHRD pRec
, uint32_t uSubClass
);
683 * Check the shared locking order.
685 * This is called by routines implementing shared lock acquisition.
687 * @retval VINF_SUCCESS on success.
688 * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all
689 * necessary whining and breakpointing before returning.
690 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
692 * @param pRec The validator record.
693 * @param hThreadSelf The handle of the calling thread. If not known,
694 * pass NIL_RTTHREAD and we'll figure it out.
695 * @param pSrcPos The source position of the lock operation.
696 * @param cMillies Intended sleep time in milliseconds.
698 RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThreadSelf
,
699 PCRTLOCKVALSRCPOS pSrcPos
, RTMSINTERVAL cMillies
);
702 * Do deadlock detection before blocking on shared access to a lock and change
705 * @retval VINF_SUCCESS - thread is in the specified sleep state.
706 * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the
708 * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
709 * already the owner. Gone thru the motions.
710 * @retval VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock.
711 * The caller must handle any legal upgrades without invoking this
712 * function (for now).
713 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
715 * @param pRec The validator record we're blocking on.
716 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
717 * @param pSrcPos The source position of the lock operation.
718 * @param fRecursiveOk Whether it's ok to recurse.
719 * @param cMillies Intended sleep time in milliseconds.
720 * @param enmSleepState The sleep state to enter on successful return.
721 * @param fReallySleeping Is it really going to sleep now or not. Use
722 * false before calls to other IPRT synchronization
725 RTDECL(int) RTLockValidatorRecSharedCheckBlocking(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThreadSelf
,
726 PCRTLOCKVALSRCPOS pSrcPos
, bool fRecursiveOk
, RTMSINTERVAL cMillies
,
727 RTTHREADSTATE enmSleepState
, bool fReallySleeping
);
730 * RTLockValidatorRecSharedCheckOrder and RTLockValidatorRecSharedCheckBlocking
731 * baked into one call.
733 * @returns Any of the statuses returned by the two APIs.
734 * @param pRec The validator record.
735 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
736 * @param pSrcPos The source position of the lock operation.
737 * @param fRecursiveOk Whether it's ok to recurse.
738 * @param cMillies Intended sleep time in milliseconds.
739 * @param enmSleepState The sleep state to enter on successful return.
740 * @param fReallySleeping Is it really going to sleep now or not. Use
741 * false before calls to other IPRT synchronization
744 RTDECL(int) RTLockValidatorRecSharedCheckOrderAndBlocking(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThreadSelf
,
745 PCRTLOCKVALSRCPOS pSrcPos
, bool fRecursiveOk
, RTMSINTERVAL cMillies
,
746 RTTHREADSTATE enmSleepState
, bool fReallySleeping
);
749 * Removes all current owners and makes hThread the only owner.
751 * @param pRec The validator record.
752 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
753 * an alias for the current thread.
754 * @param pSrcPos The source position of the lock operation.
756 RTDECL(void) RTLockValidatorRecSharedResetOwner(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThread
, PCRTLOCKVALSRCPOS pSrcPos
);
759 * Adds an owner to a shared locking record.
761 * Takes recursion into account. This function is typically called after
762 * acquiring the lock in shared mode.
764 * @param pRec The validator record.
765 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
766 * an alias for the current thread.
767 * @param pSrcPos The source position of the lock operation.
769 RTDECL(void) RTLockValidatorRecSharedAddOwner(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThread
, PCRTLOCKVALSRCPOS pSrcPos
);
772 * Removes an owner from a shared locking record.
774 * Takes recursion into account. This function is typically called before
775 * releasing the lock.
777 * @param pRec The validator record.
778 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
779 * an alias for the current thread.
781 RTDECL(void) RTLockValidatorRecSharedRemoveOwner(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThread
);
784 * Checks if the specified thread is one of the owners.
786 * @returns true if it is, false if not.
788 * @param pRec The validator record.
789 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
790 * an alias for the current thread.
792 RTDECL(bool) RTLockValidatorRecSharedIsOwner(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThread
);
795 * Check the exit order and release (unset) the shared ownership.
797 * This is called by routines implementing releasing the read/write lock.
799 * @retval VINF_SUCCESS on success.
800 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have
801 * done all necessary whining and breakpointing before returning.
802 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
804 * @param pRec The validator record.
805 * @param hThreadSelf The handle of the calling thread. NIL_RTTHREAD
806 * is an alias for the current thread.
808 RTDECL(int) RTLockValidatorRecSharedCheckAndRelease(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThreadSelf
);
811 * Check the signaller of an event.
813 * This is called by routines implementing releasing the event semaphore (both
816 * @retval VINF_SUCCESS on success.
817 * @retval VERR_SEM_LV_NOT_SIGNALLER if the thread is not in the record. Will
818 * have done all necessary whining and breakpointing before returning.
819 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
821 * @param pRec The validator record.
822 * @param hThreadSelf The handle of the calling thread. NIL_RTTHREAD
823 * is an alias for the current thread.
825 RTDECL(int) RTLockValidatorRecSharedCheckSignaller(PRTLOCKVALRECSHRD pRec
, RTTHREAD hThreadSelf
);
828 * Gets the number of write locks and critical sections the specified
831 * This number does not include any nested lock/critect entries.
833 * Note that it probably will return 0 for non-strict builds since
834 * release builds doesn't do unnecessary diagnostic counting like this.
836 * @returns Number of locks on success (0+) and VERR_INVALID_HANDLER on failure
837 * @param Thread The thread we're inquiring about.
838 * @remarks Will only work for strict builds.
840 RTDECL(int32_t) RTLockValidatorWriteLockGetCount(RTTHREAD Thread
);
843 * Works the THREADINT::cWriteLocks member, mostly internal.
845 * @param Thread The current thread.
847 RTDECL(void) RTLockValidatorWriteLockInc(RTTHREAD Thread
);
850 * Works the THREADINT::cWriteLocks member, mostly internal.
852 * @param Thread The current thread.
854 RTDECL(void) RTLockValidatorWriteLockDec(RTTHREAD Thread
);
857 * Gets the number of read locks the specified thread owns.
859 * Note that nesting read lock entry will be included in the
860 * total sum. And that it probably will return 0 for non-strict
861 * builds since release builds doesn't do unnecessary diagnostic
862 * counting like this.
864 * @returns Number of read locks on success (0+) and VERR_INVALID_HANDLER on failure
865 * @param Thread The thread we're inquiring about.
867 RTDECL(int32_t) RTLockValidatorReadLockGetCount(RTTHREAD Thread
);
870 * Works the THREADINT::cReadLocks member.
872 * @param Thread The current thread.
874 RTDECL(void) RTLockValidatorReadLockInc(RTTHREAD Thread
);
877 * Works the THREADINT::cReadLocks member.
879 * @param Thread The current thread.
881 RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread
);
884 * Query which lock the specified thread is waiting on.
886 * @returns The lock handle value or NULL.
887 * @param hThread The thread in question.
889 RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread
);
892 * Checks if the thread is running in the lock validator after it has entered a
895 * @returns true if it is, false if it isn't.
896 * @param hThread The thread in question.
898 RTDECL(bool) RTLockValidatorIsBlockedThreadInValidator(RTTHREAD hThread
);
901 * Checks if the calling thread is holding a lock in the specified class.
903 * @returns true if it holds a lock in the specific class, false if it
906 * @param hCurrentThread The current thread. Pass NIL_RTTHREAD if you're
908 * @param hClass The class.
910 RTDECL(bool) RTLockValidatorHoldsLocksInClass(RTTHREAD hCurrentThread
, RTLOCKVALCLASS hClass
);
913 * Checks if the calling thread is holding a lock in the specified sub-class.
915 * @returns true if it holds a lock in the specific sub-class, false if it
918 * @param hCurrentThread The current thread. Pass NIL_RTTHREAD if you're
920 * @param hClass The class.
921 * @param uSubClass The new sub-class value.
923 RTDECL(bool) RTLockValidatorHoldsLocksInSubClass(RTTHREAD hCurrentThread
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
);
928 * Creates a new lock validator class, all properties specified.
930 * @returns IPRT status code
931 * @param phClass Where to return the class handle.
932 * @param pSrcPos The source position of the create call.
933 * @param fAutodidact Whether the class should be allowed to teach
934 * itself new locking order rules (true), or if the
935 * user will teach it all it needs to know (false).
936 * @param fRecursionOk Whether to allow lock recursion or not.
937 * @param fStrictReleaseOrder Enforce strict lock release order or not.
938 * @param cMsMinDeadlock Used to raise the sleep interval at which
939 * deadlock detection kicks in. Minimum is 1 ms,
940 * while RT_INDEFINITE_WAIT will disable it.
941 * @param cMsMinOrder Used to raise the sleep interval at which lock
942 * order validation kicks in. Minimum is 1 ms,
943 * while RT_INDEFINITE_WAIT will disable it.
944 * @param pszNameFmt Class name format string, optional (NULL). Max
945 * length is 32 bytes.
946 * @param ... Format string arguments.
948 * @remarks The properties can be modified after creation by the
949 * RTLockValidatorClassSet* methods.
951 RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass
, PCRTLOCKVALSRCPOS pSrcPos
,
952 bool fAutodidact
, bool fRecursionOk
, bool fStrictReleaseOrder
,
953 RTMSINTERVAL cMsMinDeadlock
, RTMSINTERVAL cMsMinOrder
,
954 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(8, 9);
957 * Creates a new lock validator class, all properties specified.
959 * @returns IPRT status code
960 * @param phClass Where to return the class handle.
961 * @param pSrcPos The source position of the create call.
962 * @param fAutodidact Whether the class should be allowed to teach
963 * itself new locking order rules (true), or if the
964 * user will teach it all it needs to know (false).
965 * @param fRecursionOk Whether to allow lock recursion or not.
966 * @param fStrictReleaseOrder Enforce strict lock release order or not.
967 * @param cMsMinDeadlock Used to raise the sleep interval at which
968 * deadlock detection kicks in. Minimum is 1 ms,
969 * while RT_INDEFINITE_WAIT will disable it.
970 * @param cMsMinOrder Used to raise the sleep interval at which lock
971 * order validation kicks in. Minimum is 1 ms,
972 * while RT_INDEFINITE_WAIT will disable it.
973 * @param pszNameFmt Class name format string, optional (NULL). Max
974 * length is 32 bytes.
975 * @param va Format string arguments.
977 * @remarks The properties can be modified after creation by the
978 * RTLockValidatorClassSet* methods.
980 RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass
, PCRTLOCKVALSRCPOS pSrcPos
,
981 bool fAutodidact
, bool fRecursionOk
, bool fStrictReleaseOrder
,
982 RTMSINTERVAL cMsMinDeadlock
, RTMSINTERVAL cMsMinOrder
,
983 const char *pszNameFmt
, va_list va
) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(8, 0);
986 * Creates a new lock validator class.
988 * @returns IPRT status code
989 * @param phClass Where to return the class handle.
990 * @param fAutodidact Whether the class should be allowed to teach
991 * itself new locking order rules (true), or if the
992 * user will teach it all it needs to know (false).
993 * @param SRC_POS The source position where call is being made from.
994 * Use RT_SRC_POS when possible. Optional.
995 * @param pszNameFmt Class name format string, optional (NULL). Max
996 * length is 32 bytes.
997 * @param ... Format string arguments.
999 RTDECL(int) RTLockValidatorClassCreate(PRTLOCKVALCLASS phClass
, bool fAutodidact
, RT_SRC_POS_DECL
,
1000 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
1003 * Creates a new lock validator class with a reference that is consumed by the
1004 * first call to RTLockValidatorClassRetain.
1006 * This is tailored for use in the parameter list of a semaphore constructor.
1008 * @returns Class handle with a reference that is automatically consumed by the
1009 * first retainer. NIL_RTLOCKVALCLASS if we run into trouble.
1011 * @param SRC_POS The source position where call is being made from.
1012 * Use RT_SRC_POS when possible. Optional.
1013 * @param pszNameFmt Class name format string, optional (NULL). Max
1014 * length is 32 bytes.
1015 * @param ... Format string arguments.
1017 RTDECL(RTLOCKVALCLASS
) RTLockValidatorClassCreateUnique(RT_SRC_POS_DECL
,
1018 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
1021 * Finds a class for the specified source position.
1023 * @returns A handle to the class (not retained!) or NIL_RTLOCKVALCLASS.
1024 * @param pSrcPos The source position.
1026 RTDECL(RTLOCKVALCLASS
) RTLockValidatorClassFindForSrcPos(PRTLOCKVALSRCPOS pSrcPos
);
1029 * Finds or creates a class given the source position.
1031 * @returns Class handle (not retained!) or NIL_RTLOCKVALCLASS.
1032 * @param SRC_POS The source position where call is being made from.
1033 * Use RT_SRC_POS when possible. Optional.
1034 * @param pszNameFmt Class name format string, optional (NULL). Max
1035 * length is 32 bytes.
1036 * @param ... Format string arguments.
1038 RTDECL(RTLOCKVALCLASS
) RTLockValidatorClassForSrcPos(RT_SRC_POS_DECL
,
1039 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
1042 * Retains a reference to a lock validator class.
1044 * @returns New reference count; UINT32_MAX if the handle is invalid.
1045 * @param hClass Handle to the class.
1047 RTDECL(uint32_t) RTLockValidatorClassRetain(RTLOCKVALCLASS hClass
);
1050 * Releases a reference to a lock validator class.
1052 * @returns New reference count. 0 if hClass is NIL_RTLOCKVALCLASS. UINT32_MAX
1053 * if the handle is invalid.
1054 * @param hClass Handle to the class.
1056 RTDECL(uint32_t) RTLockValidatorClassRelease(RTLOCKVALCLASS hClass
);
1059 * Teaches the class @a hClass that locks in the class @a hPriorClass can be
1060 * held when taking a lock of class @a hClass
1062 * @returns IPRT status.
1063 * @param hClass Handle to the pupil class.
1064 * @param hPriorClass Handle to the class that can be held prior to
1065 * taking a lock in the pupil class. (No reference
1068 RTDECL(int) RTLockValidatorClassAddPriorClass(RTLOCKVALCLASS hClass
, RTLOCKVALCLASS hPriorClass
);
1071 * Enables or disables the strict release order enforcing.
1073 * @returns IPRT status.
1074 * @param hClass Handle to the class to change.
1075 * @param fEnabled Enable it (true) or disable it (false).
1077 RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass
, bool fEnabled
);
1080 * Enables / disables the lock validator for new locks.
1082 * @returns The old setting.
1083 * @param fEnabled The new setting.
1085 RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled
);
1088 * Is the lock validator enabled?
1090 * @returns True if enabled, false if not.
1092 RTDECL(bool) RTLockValidatorIsEnabled(void);
1095 * Controls whether the lock validator should be quiet or noisy (default).
1097 * @returns The old setting.
1098 * @param fQuiet The new setting.
1100 RTDECL(bool) RTLockValidatorSetQuiet(bool fQuiet
);
1103 * Is the lock validator quiet or noisy?
1105 * @returns True if it is quiet, false if noisy.
1107 RTDECL(bool) RTLockValidatorIsQuiet(void);
1110 * Makes the lock validator panic (default) or not.
1112 * @returns The old setting.
1113 * @param fPanic The new setting.
1115 RTDECL(bool) RTLockValidatorSetMayPanic(bool fPanic
);
1118 * Can the lock validator cause panic.
1120 * @returns True if it can, false if not.
1122 RTDECL(bool) RTLockValidatorMayPanic(void);