VirtualBox

source: vbox/trunk/include/iprt/lockvalidator.h@ 26201

Last change on this file since 26201 was 25908, checked in by vboxsync, 15 years ago

RTSemRWIsReadOwner: For assertion in main.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.3 KB
Line 
1/** @file
2 * IPRT - Lock Validator.
3 */
4
5/*
6 * Copyright (C) 2009 Sun Microsystems, Inc.
7 *
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.
15 *
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.
21 *
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.
24 *
25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
27 * additional information or have any questions.
28 */
29
30#ifndef ___iprt_lockvalidator_h
31#define ___iprt_lockvalidator_h
32
33#include <iprt/cdefs.h>
34#include <iprt/types.h>
35#include <iprt/assert.h>
36#include <iprt/thread.h>
37#include <iprt/stdarg.h>
38
39
40/** @defgroup grp_rtlockval RTLockValidator - Lock Validator
41 * @ingroup grp_rt
42 * @{
43 */
44
45RT_C_DECLS_BEGIN
46
47/** Pointer to a record union.
48 * @internal */
49typedef union RTLOCKVALRECUNION *PRTLOCKVALRECUNION;
50
51/**
52 * Source position.
53 */
54typedef struct RTLOCKVALSRCPOS
55{
56 /** The file where the lock was taken. */
57 R3R0PTRTYPE(const char * volatile) pszFile;
58 /** The function where the lock was taken. */
59 R3R0PTRTYPE(const char * volatile) pszFunction;
60 /** Some ID indicating where the lock was taken, typically an address. */
61 RTHCUINTPTR volatile uId;
62 /** The line number in the file. */
63 uint32_t volatile uLine;
64#if HC_ARCH_BITS == 64
65 uint32_t u32Padding; /**< Alignment padding. */
66#endif
67} RTLOCKVALSRCPOS;
68AssertCompileSize(RTLOCKVALSRCPOS, HC_ARCH_BITS == 32 ? 16 : 32);
69/* The pointer types are defined in iprt/types.h. */
70
71/** @def RTLOCKVALSRCPOS_INIT
72 * Initializer for a RTLOCKVALSRCPOS variable.
73 *
74 * @param pszFile The file name. Optional (NULL).
75 * @param uLine The line number in that file. Optional (0).
76 * @param pszFunction The function. Optional (NULL).
77 * @param uId Some location ID, normally the return address.
78 * Optional (NULL).
79 */
80#if HC_ARCH_BITS == 64
81# define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \
82 { (pszFile), (pszFunction), (uId), (uLine), 0 }
83#else
84# define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \
85 { (pszFile), (pszFunction), (uId), (uLine) }
86#endif
87
88/** @def RTLOCKVALSRCPOS_INIT_DEBUG_API
89 * Initializer for a RTLOCKVALSRCPOS variable in a typicial debug API
90 * variant. Assumes RT_SRC_POS_DECL and RTHCUINTPTR uId as arguments.
91 */
92#define RTLOCKVALSRCPOS_INIT_DEBUG_API() \
93 RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, uId)
94
95/** @def RTLOCKVALSRCPOS_INIT_NORMAL_API
96 * Initializer for a RTLOCKVALSRCPOS variable in a normal API
97 * variant. Assumes iprt/asm.h is included.
98 */
99#define RTLOCKVALSRCPOS_INIT_NORMAL_API() \
100 RTLOCKVALSRCPOS_INIT(__FILE__, __LINE__, __PRETTY_FUNCTION__, (uintptr_t)ASMReturnAddress())
101
102/** @def RTLOCKVALSRCPOS_INIT_POS_NO_ID
103 * Initializer for a RTLOCKVALSRCPOS variable when no @c uId is present.
104 * Assumes iprt/asm.h is included.
105 */
106#define RTLOCKVALSRCPOS_INIT_POS_NO_ID() \
107 RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, (uintptr_t)ASMReturnAddress())
108
109/** Pointer to a record of one ownership share. */
110typedef struct RTLOCKVALRECSHRD *PRTLOCKVALRECSHRD;
111
112
113/**
114 * Lock validator record core.
115 */
116typedef struct RTLOCKVALRECORE
117{
118 /** The magic value indicating the record type. */
119 uint32_t volatile u32Magic;
120} RTLOCKVALRECCORE;
121/** Pointer to a lock validator record core. */
122typedef RTLOCKVALRECCORE *PRTLOCKVALRECCORE;
123/** Pointer to a const lock validator record core. */
124typedef RTLOCKVALRECCORE const *PCRTLOCKVALRECCORE;
125
126
127/**
128 * Record recording the exclusive ownership of a lock.
129 *
130 * This is typically part of the per-lock data structure when compiling with
131 * the lock validator.
132 */
133typedef struct RTLOCKVALRECEXCL
134{
135 /** Record core with RTLOCKVALRECEXCL_MAGIC as the magic value. */
136 RTLOCKVALRECCORE Core;
137 /** Whether it's enabled or not. */
138 bool fEnabled;
139 /** Reserved. */
140 bool afReserved[3];
141 /** Source position where the lock was taken. */
142 RTLOCKVALSRCPOS SrcPos;
143 /** The current owner thread. */
144 RTTHREAD volatile hThread;
145 /** Pointer to the lock record below us. Only accessed by the owner. */
146 R3R0PTRTYPE(PRTLOCKVALRECUNION) pDown;
147 /** Recursion count */
148 uint32_t cRecursion;
149 /** The lock sub-class. */
150 uint32_t volatile uSubClass;
151 /** The lock class. */
152 RTLOCKVALCLASS hClass;
153 /** Pointer to the lock. */
154 RTHCPTR hLock;
155 /** Pointer to the next sibling record.
156 * This is used to find the read side of a read-write lock. */
157 R3R0PTRTYPE(PRTLOCKVALRECUNION) pSibling;
158 /** The lock name.
159 * @remarks The bytes beyond 32 are for better size alignment and can be
160 * taken and used for other purposes if it becomes necessary. */
161 char szName[32 + (HC_ARCH_BITS == 32 ? 12 : 8)];
162} RTLOCKVALRECEXCL;
163AssertCompileSize(RTLOCKVALRECEXCL, HC_ARCH_BITS == 32 ? 0x60 : 0x80);
164/* The pointer type is defined in iprt/types.h. */
165
166/**
167 * For recording the one ownership share.
168 */
169typedef struct RTLOCKVALRECSHRDOWN
170{
171 /** Record core with RTLOCKVALRECSHRDOWN_MAGIC as the magic value. */
172 RTLOCKVALRECCORE Core;
173 /** Recursion count */
174 uint16_t cRecursion;
175 /** Static (true) or dynamic (false) allocated record. */
176 bool fStaticAlloc;
177 /** Reserved. */
178 bool fReserved;
179 /** The current owner thread. */
180 RTTHREAD volatile hThread;
181 /** Pointer to the lock record below us. Only accessed by the owner. */
182 R3R0PTRTYPE(PRTLOCKVALRECUNION) pDown;
183 /** Pointer back to the shared record. */
184 R3R0PTRTYPE(PRTLOCKVALRECSHRD) pSharedRec;
185#if HC_ARCH_BITS == 32
186 /** Reserved. */
187 RTHCPTR pvReserved;
188#endif
189 /** Source position where the lock was taken. */
190 RTLOCKVALSRCPOS SrcPos;
191} RTLOCKVALRECSHRDOWN;
192AssertCompileSize(RTLOCKVALRECSHRDOWN, HC_ARCH_BITS == 32 ? 24 + 16 : 32 + 32);
193/** Pointer to a RTLOCKVALRECSHRDOWN. */
194typedef RTLOCKVALRECSHRDOWN *PRTLOCKVALRECSHRDOWN;
195
196/**
197 * Record recording the shared ownership of a lock.
198 *
199 * This is typically part of the per-lock data structure when compiling with
200 * the lock validator.
201 */
202typedef struct RTLOCKVALRECSHRD
203{
204 /** Record core with RTLOCKVALRECSHRD_MAGIC as the magic value. */
205 RTLOCKVALRECCORE Core;
206 /** The lock sub-class. */
207 uint32_t volatile uSubClass;
208 /** The lock class. */
209 RTLOCKVALCLASS hClass;
210 /** Pointer to the lock. */
211 RTHCPTR hLock;
212 /** Pointer to the next sibling record.
213 * This is used to find the write side of a read-write lock. */
214 R3R0PTRTYPE(PRTLOCKVALRECUNION) pSibling;
215
216 /** The number of entries in the table.
217 * Updated before inserting and after removal. */
218 uint32_t volatile cEntries;
219 /** The index of the last entry (approximately). */
220 uint32_t volatile iLastEntry;
221 /** The max table size. */
222 uint32_t volatile cAllocated;
223 /** Set if the table is being reallocated, clear if not.
224 * This is used together with rtLockValidatorSerializeDetectionEnter to make
225 * sure there is exactly one thread doing the reallocation and that nobody is
226 * using the table at that point. */
227 bool volatile fReallocating;
228 /** Whether it's enabled or not. */
229 bool fEnabled;
230 /** Set if event semaphore signaller, clear if read-write semaphore. */
231 bool fSignaller;
232 /** Alignment padding. */
233 bool fPadding;
234 /** Pointer to a table containing pointers to records of all the owners. */
235 R3R0PTRTYPE(PRTLOCKVALRECSHRDOWN volatile *) papOwners;
236
237 /** The lock name.
238 * @remarks The bytes beyond 32 are for better size alignment and can be
239 * taken and used for other purposes if it becomes necessary. */
240 char szName[32 + (HC_ARCH_BITS == 32 ? 8 : 8)];
241} RTLOCKVALRECSHRD;
242AssertCompileSize(RTLOCKVALRECSHRD, HC_ARCH_BITS == 32 ? 0x50 : 0x60);
243
244
245/**
246 * Makes the two records siblings.
247 *
248 * @returns VINF_SUCCESS on success, VERR_SEM_LV_INVALID_PARAMETER if either of
249 * the records are invalid.
250 * @param pRec1 Record 1.
251 * @param pRec2 Record 2.
252 */
253RTDECL(int) RTLockValidatorRecMakeSiblings(PRTLOCKVALRECCORE pRec1, PRTLOCKVALRECCORE pRec2);
254
255/**
256 * Initialize a lock validator record.
257 *
258 * Use RTLockValidatorRecExclDelete to deinitialize it.
259 *
260 * @param pRec The record.
261 * @param hClass The class (no reference consumed). If NIL, the
262 * no lock order validation will be performed on
263 * this lock.
264 * @param uSubClass The sub-class. This is used to define lock
265 * order inside the same class. If you don't know,
266 * then pass RTLOCKVAL_SUB_CLASS_NONE.
267 * @param hLock The lock handle.
268 * @param fEnabled Pass @c false to explicitly disable lock
269 * validation, otherwise @c true.
270 * @param pszNameFmt Name format string for the lock validator,
271 * optional (NULL). Max length is 32 bytes.
272 * @param ... Format string arguments.
273 */
274RTDECL(void) RTLockValidatorRecExclInit(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
275 void *hLock, bool fEnabled, const char *pszNameFmt, ...);
276/**
277 * Initialize a lock validator record.
278 *
279 * Use RTLockValidatorRecExclDelete to deinitialize it.
280 *
281 * @param pRec The record.
282 * @param hClass The class (no reference consumed). If NIL, the
283 * no lock order validation will be performed on
284 * this lock.
285 * @param uSubClass The sub-class. This is used to define lock
286 * order inside the same class. If you don't know,
287 * then pass RTLOCKVAL_SUB_CLASS_NONE.
288 * @param hLock The lock handle.
289 * @param fEnabled Pass @c false to explicitly disable lock
290 * validation, otherwise @c true.
291 * @param pszNameFmt Name format string for the lock validator,
292 * optional (NULL). Max length is 32 bytes.
293 * @param va Format string arguments.
294 */
295RTDECL(void) RTLockValidatorRecExclInitV(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
296 void *hLock, bool fEnabled, const char *pszNameFmt, va_list va);
297/**
298 * Uninitialize a lock validator record previously initialized by
299 * RTLockRecValidatorInit.
300 *
301 * @param pRec The record. Must be valid.
302 */
303RTDECL(void) RTLockValidatorRecExclDelete(PRTLOCKVALRECEXCL pRec);
304
305/**
306 * Create and initialize a lock validator record.
307 *
308 * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned
309 * record.
310 *
311 * @return VINF_SUCCESS or VERR_NO_MEMORY.
312 * @param ppRec Where to return the record pointer.
313 * @param hClass The class (no reference consumed). If NIL, the
314 * no lock order validation will be performed on
315 * this lock.
316 * @param uSubClass The sub-class. This is used to define lock
317 * order inside the same class. If you don't know,
318 * then pass RTLOCKVAL_SUB_CLASS_NONE.
319 * @param hLock The lock handle.
320 * @param fEnabled Pass @c false to explicitly disable lock
321 * validation, otherwise @c true.
322 * @param pszNameFmt Name format string for the lock validator,
323 * optional (NULL). Max length is 32 bytes.
324 * @param ... Format string arguments.
325 */
326RTDECL(int) RTLockValidatorRecExclCreate(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
327 void *hLock, bool fEnabled, const char *pszNameFmt, ...);
328
329/**
330 * Create and initialize a lock validator record.
331 *
332 * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned
333 * record.
334 *
335 * @return VINF_SUCCESS or VERR_NO_MEMORY.
336 * @param ppRec Where to return the record pointer.
337 * @param hClass The class (no reference consumed). If NIL, the
338 * no lock order validation will be performed on
339 * this lock.
340 * @param uSubClass The sub-class. This is used to define lock
341 * order inside the same class. If you don't know,
342 * then pass RTLOCKVAL_SUB_CLASS_NONE.
343 * @param hLock The lock handle.
344 * @param fEnabled Pass @c false to explicitly disable lock
345 * validation, otherwise @c true.
346 * @param pszNameFmt Name format string for the lock validator,
347 * optional (NULL). Max length is 32 bytes.
348 * @param va Format string arguments.
349 */
350RTDECL(int) RTLockValidatorRecExclCreateV(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
351 void *hLock, bool fEnabled, const char *pszNameFmt, va_list va);
352
353/**
354 * Deinitialize and destroy a record created by RTLockValidatorRecExclCreate.
355 *
356 * @param ppRec Pointer to the record pointer. Will be set to
357 * NULL.
358 */
359RTDECL(void) RTLockValidatorRecExclDestroy(PRTLOCKVALRECEXCL *ppRec);
360
361/**
362 * Sets the sub-class of the record.
363 *
364 * It is recommended to try make sure that nobody is using this class while
365 * changing the value.
366 *
367 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
368 * lock validator isn't compiled in or either of the parameters are
369 * invalid.
370 * @param pRec The validator record.
371 * @param uSubClass The new sub-class value.
372 */
373RTDECL(uint32_t) RTLockValidatorRecExclSetSubClass(PRTLOCKVALRECEXCL pRec, uint32_t uSubClass);
374
375/**
376 * Record the specified thread as lock owner and increment the write lock count.
377 *
378 * This function is typically called after acquiring the lock. It accounts for
379 * recursions so it can be used instead of RTLockValidatorRecExclRecursion. Use
380 * RTLockValidatorRecExclReleaseOwner to reverse the effect.
381 *
382 * @param pRec The validator record.
383 * @param hThreadSelf The handle of the calling thread. If not known,
384 * pass NIL_RTTHREAD and we'll figure it out.
385 * @param pSrcPos The source position of the lock operation.
386 * @param fFirstRecursion Set if it is the first recursion, clear if not
387 * sure.
388 */
389RTDECL(void) RTLockValidatorRecExclSetOwner(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
390 PCRTLOCKVALSRCPOS pSrcPos, bool fFirstRecursion);
391
392/**
393 * Check the exit order and release (unset) the ownership.
394 *
395 * This is called by routines implementing releasing an exclusive lock,
396 * typically before getting down to the final lock releaseing. Can be used for
397 * recursive releasing instead of RTLockValidatorRecExclUnwind.
398 *
399 * @retval VINF_SUCCESS on success.
400 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have
401 * done all necessary whining and breakpointing before returning.
402 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
403 *
404 * @param pRec The validator record.
405 * @param fFinalRecursion Set if it's the final recursion, clear if not
406 * sure.
407 */
408RTDECL(int) RTLockValidatorRecExclReleaseOwner(PRTLOCKVALRECEXCL pRec, bool fFinalRecursion);
409
410/**
411 * Clear the lock ownership and decrement the write lock count.
412 *
413 * This is only for special cases where we wish to drop lock validation
414 * recording. See RTLockValidatorRecExclCheckAndRelease.
415 *
416 * @param pRec The validator record.
417 */
418RTDECL(void) RTLockValidatorRecExclReleaseOwnerUnchecked(PRTLOCKVALRECEXCL pRec);
419
420/**
421 * Checks and records a lock recursion.
422 *
423 * @retval VINF_SUCCESS on success.
424 * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone
425 * thru the motions.
426 * @retval VERR_SEM_LV_WRONG_ORDER if the locking order is wrong. Gone thru
427 * the motions.
428 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
429 *
430 * @param pRec The validator record.
431 * @param pSrcPos The source position of the lock operation.
432 */
433RTDECL(int) RTLockValidatorRecExclRecursion(PRTLOCKVALRECEXCL pRec, PCRTLOCKVALSRCPOS pSrcPos);
434
435/**
436 * Checks and records a lock unwind (releasing one recursion).
437 *
438 * This should be coupled with called to RTLockValidatorRecExclRecursion.
439 *
440 * @retval VINF_SUCCESS on success.
441 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong. Gone
442 * thru the motions.
443 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
444 *
445 * @param pRec The validator record.
446 */
447RTDECL(int) RTLockValidatorRecExclUnwind(PRTLOCKVALRECEXCL pRec);
448
449/**
450 * Checks and records a mixed recursion.
451 *
452 * An example of a mixed recursion is a writer requesting read access to a
453 * SemRW.
454 *
455 * This should be coupled with called to RTLockValidatorRecExclUnwindMixed.
456 *
457 * @retval VINF_SUCCESS on success.
458 * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone
459 * thru the motions.
460 * @retval VERR_SEM_LV_WRONG_ORDER if the locking order is wrong. Gone thru
461 * the motions.
462 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
463 *
464 * @param pRec The validator record it to accounted it to.
465 * @param pRecMixed The validator record it came in on.
466 * @param pSrcPos The source position of the lock operation.
467 */
468RTDECL(int) RTLockValidatorRecExclRecursionMixed(PRTLOCKVALRECEXCL pRec, PRTLOCKVALRECCORE pRecMixed, PCRTLOCKVALSRCPOS pSrcPos);
469
470/**
471 * Checks and records the unwinding of a mixed recursion.
472 *
473 * This should be coupled with called to RTLockValidatorRecExclRecursionMixed.
474 *
475 * @retval VINF_SUCCESS on success.
476 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong. Gone
477 * thru the motions.
478 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
479 *
480 * @param pRec The validator record it was accounted to.
481 * @param pRecMixed The validator record it came in on.
482 */
483RTDECL(int) RTLockValidatorRecExclUnwindMixed(PRTLOCKVALRECEXCL pRec, PRTLOCKVALRECCORE pRecMixed);
484
485/**
486 * Check the exclusive locking order.
487 *
488 * This is called by routines implementing exclusive lock acquisition.
489 *
490 * @retval VINF_SUCCESS on success.
491 * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all
492 * necessary whining and breakpointing before returning.
493 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
494 *
495 * @param pRec The validator record.
496 * @param hThreadSelf The handle of the calling thread. If not known,
497 * pass NIL_RTTHREAD and we'll figure it out.
498 * @param pSrcPos The source position of the lock operation.
499 * @param cMillies The timeout, in milliseconds.
500 */
501RTDECL(int) RTLockValidatorRecExclCheckOrder(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
502 PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies);
503
504/**
505 * Do deadlock detection before blocking on exclusive access to a lock and
506 * change the thread state.
507 *
508 * @retval VINF_SUCCESS - thread is in the specified sleep state.
509 * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the
510 * motions.
511 * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
512 * already the owner. Gone thru the motions.
513 * @retval VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock.
514 * The caller must handle any legal upgrades without invoking this
515 * function (for now).
516 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
517 *
518 * @param pRec The validator record we're blocking on.
519 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
520 * @param pSrcPos The source position of the lock operation.
521 * @param fRecursiveOk Whether it's ok to recurse.
522 * @param cMillies The timeout, in milliseconds.
523 * @param enmSleepState The sleep state to enter on successful return.
524 * @param fReallySleeping Is it really going to sleep now or not. Use
525 * false before calls to other IPRT synchronization
526 * methods.
527 */
528RTDECL(int) RTLockValidatorRecExclCheckBlocking(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
529 PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
530 RTTHREADSTATE enmSleepState, bool fReallySleeping);
531
532/**
533 * RTLockValidatorRecExclCheckOrder and RTLockValidatorRecExclCheckBlocking
534 * baked into one call.
535 *
536 * @returns Any of the statuses returned by the two APIs.
537 * @param pRec The validator record.
538 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
539 * @param pSrcPos The source position of the lock operation.
540 * @param fRecursiveOk Whether it's ok to recurse.
541 * @param cMillies The timeout, in milliseconds.
542 * @param enmSleepState The sleep state to enter on successful return.
543 * @param fReallySleeping Is it really going to sleep now or not. Use
544 * false before calls to other IPRT synchronization
545 * methods.
546 */
547RTDECL(int) RTLockValidatorRecExclCheckOrderAndBlocking(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf,
548 PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
549 RTTHREADSTATE enmSleepState, bool fReallySleeping);
550
551/**
552 * Initialize a lock validator record for a shared lock.
553 *
554 * Use RTLockValidatorRecSharedDelete to deinitialize it.
555 *
556 * @param pRec The shared lock record.
557 * @param hClass The class (no reference consumed). If NIL, the
558 * no lock order validation will be performed on
559 * this lock.
560 * @param uSubClass The sub-class. This is used to define lock
561 * order inside the same class. If you don't know,
562 * then pass RTLOCKVAL_SUB_CLASS_NONE.
563 * @param hLock The lock handle.
564 * @param fSignaller Set if event semaphore signaller logic should be
565 * applied to this record, clear if read-write
566 * semaphore logic should be used.
567 * @param fEnabled Pass @c false to explicitly disable lock
568 * validation, otherwise @c true.
569 * @param pszNameFmt Name format string for the lock validator,
570 * optional (NULL). Max length is 32 bytes.
571 * @param ... Format string arguments.
572 */
573RTDECL(void) RTLockValidatorRecSharedInit(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
574 void *hLock, bool fSignaller, bool fEnabled, const char *pszNameFmt, ...);
575/**
576 * Initialize a lock validator record for a shared lock.
577 *
578 * Use RTLockValidatorRecSharedDelete to deinitialize it.
579 *
580 * @param pRec The shared lock record.
581 * @param hClass The class (no reference consumed). If NIL, the
582 * no lock order validation will be performed on
583 * this lock.
584 * @param uSubClass The sub-class. This is used to define lock
585 * order inside the same class. If you don't know,
586 * then pass RTLOCKVAL_SUB_CLASS_NONE.
587 * @param hLock The lock handle.
588 * @param fSignaller Set if event semaphore signaller logic should be
589 * applied to this record, clear if read-write
590 * semaphore logic should be used.
591 * @param fEnabled Pass @c false to explicitly disable lock
592 * validation, otherwise @c true.
593 * @param pszNameFmt Name format string for the lock validator,
594 * optional (NULL). Max length is 32 bytes.
595 * @param va Format string arguments.
596 */
597RTDECL(void) RTLockValidatorRecSharedInitV(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
598 void *hLock, bool fSignaller, bool fEnabled, const char *pszNameFmt, va_list va);
599/**
600 * Uninitialize a lock validator record previously initialized by
601 * RTLockValidatorRecSharedInit.
602 *
603 * @param pRec The shared lock record. Must be valid.
604 */
605RTDECL(void) RTLockValidatorRecSharedDelete(PRTLOCKVALRECSHRD pRec);
606
607/**
608 * Sets the sub-class of the record.
609 *
610 * It is recommended to try make sure that nobody is using this class while
611 * changing the value.
612 *
613 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
614 * lock validator isn't compiled in or either of the parameters are
615 * invalid.
616 * @param pRec The validator record.
617 * @param uSubClass The new sub-class value.
618 */
619RTDECL(uint32_t) RTLockValidatorRecSharedSetSubClass(PRTLOCKVALRECSHRD pRec, uint32_t uSubClass);
620
621/**
622 * Check the shared locking order.
623 *
624 * This is called by routines implementing shared lock acquisition.
625 *
626 * @retval VINF_SUCCESS on success.
627 * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all
628 * necessary whining and breakpointing before returning.
629 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
630 *
631 * @param pRec The validator record.
632 * @param hThreadSelf The handle of the calling thread. If not known,
633 * pass NIL_RTTHREAD and we'll figure it out.
634 * @param pSrcPos The source position of the lock operation.
635 */
636RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
637 PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies);
638
639/**
640 * Do deadlock detection before blocking on shared access to a lock and change
641 * the thread state.
642 *
643 * @retval VINF_SUCCESS - thread is in the specified sleep state.
644 * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the
645 * motions.
646 * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
647 * already the owner. Gone thru the motions.
648 * @retval VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock.
649 * The caller must handle any legal upgrades without invoking this
650 * function (for now).
651 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
652 *
653 * @param pRec The validator record we're blocking on.
654 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
655 * @param pSrcPos The source position of the lock operation.
656 * @param fRecursiveOk Whether it's ok to recurse.
657 * @param enmSleepState The sleep state to enter on successful return.
658 * @param fReallySleeping Is it really going to sleep now or not. Use
659 * false before calls to other IPRT synchronization
660 * methods.
661 */
662RTDECL(int) RTLockValidatorRecSharedCheckBlocking(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
663 PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
664 RTTHREADSTATE enmSleepState, bool fReallySleeping);
665
666/**
667 * RTLockValidatorRecSharedCheckOrder and RTLockValidatorRecSharedCheckBlocking
668 * baked into one call.
669 *
670 * @returns Any of the statuses returned by the two APIs.
671 * @param pRec The validator record.
672 * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD!
673 * @param pSrcPos The source position of the lock operation.
674 * @param fRecursiveOk Whether it's ok to recurse.
675 * @param enmSleepState The sleep state to enter on successful return.
676 * @param fReallySleeping Is it really going to sleep now or not. Use
677 * false before calls to other IPRT synchronization
678 * methods.
679 */
680RTDECL(int) RTLockValidatorRecSharedCheckOrderAndBlocking(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf,
681 PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies,
682 RTTHREADSTATE enmSleepState, bool fReallySleeping);
683
684/**
685 * Removes all current owners and makes hThread the only owner.
686 *
687 * @param pRec The validator record.
688 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
689 * an alias for the current thread.
690 * @param pSrcPos The source position of the lock operation.
691 */
692RTDECL(void) RTLockValidatorRecSharedResetOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos);
693
694/**
695 * Adds an owner to a shared locking record.
696 *
697 * Takes recursion into account. This function is typically called after
698 * acquiring the lock in shared mode.
699 *
700 * @param pRec The validator record.
701 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
702 * an alias for the current thread.
703 * @param pSrcPos The source position of the lock operation.
704 */
705RTDECL(void) RTLockValidatorRecSharedAddOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos);
706
707/**
708 * Removes an owner from a shared locking record.
709 *
710 * Takes recursion into account. This function is typically called before
711 * releaseing the lock.
712 *
713 * @param pRec The validator record.
714 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
715 * an alias for the current thread.
716 */
717RTDECL(void) RTLockValidatorRecSharedRemoveOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread);
718
719/**
720 * Checks if the specified thread is one of the owners.
721 *
722 * @returns true if it is, false if not.
723 *
724 * @param pRec The validator record.
725 * @param hThread The thread handle of the owner. NIL_RTTHREAD is
726 * an alias for the current thread.
727 */
728RTDECL(bool) RTLockValidatorRecSharedIsOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread);
729
730/**
731 * Check the exit order and release (unset) the shared ownership.
732 *
733 * This is called by routines implementing releasing the read/write lock.
734 *
735 * @retval VINF_SUCCESS on success.
736 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have
737 * done all necessary whining and breakpointing before returning.
738 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
739 *
740 * @param pRec The validator record.
741 * @param hThreadSelf The handle of the calling thread. NIL_RTTHREAD
742 * is an alias for the current thread.
743 */
744RTDECL(int) RTLockValidatorRecSharedCheckAndRelease(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf);
745
746/**
747 * Check the signaller of an event.
748 *
749 * This is called by routines implementing releasing the event sempahore (both
750 * kinds).
751 *
752 * @retval VINF_SUCCESS on success.
753 * @retval VERR_SEM_LV_NOT_SIGNALLER if the thread is not in the record. Will
754 * have done all necessary whining and breakpointing before returning.
755 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
756 *
757 * @param pRec The validator record.
758 * @param hThreadSelf The handle of the calling thread. NIL_RTTHREAD
759 * is an alias for the current thread.
760 */
761RTDECL(int) RTLockValidatorRecSharedCheckSignaller(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf);
762
763/**
764 * Gets the number of write locks and critical sections the specified
765 * thread owns.
766 *
767 * This number does not include any nested lock/critect entries.
768 *
769 * Note that it probably will return 0 for non-strict builds since
770 * release builds doesn't do unnecessary diagnostic counting like this.
771 *
772 * @returns Number of locks on success (0+) and VERR_INVALID_HANDLER on failure
773 * @param Thread The thread we're inquiring about.
774 * @remarks Will only work for strict builds.
775 */
776RTDECL(int32_t) RTLockValidatorWriteLockGetCount(RTTHREAD Thread);
777
778/**
779 * Works the THREADINT::cWriteLocks member, mostly internal.
780 *
781 * @param Thread The current thread.
782 */
783RTDECL(void) RTLockValidatorWriteLockInc(RTTHREAD Thread);
784
785/**
786 * Works the THREADINT::cWriteLocks member, mostly internal.
787 *
788 * @param Thread The current thread.
789 */
790RTDECL(void) RTLockValidatorWriteLockDec(RTTHREAD Thread);
791
792/**
793 * Gets the number of read locks the specified thread owns.
794 *
795 * Note that nesting read lock entry will be included in the
796 * total sum. And that it probably will return 0 for non-strict
797 * builds since release builds doesn't do unnecessary diagnostic
798 * counting like this.
799 *
800 * @returns Number of read locks on success (0+) and VERR_INVALID_HANDLER on failure
801 * @param Thread The thread we're inquiring about.
802 */
803RTDECL(int32_t) RTLockValidatorReadLockGetCount(RTTHREAD Thread);
804
805/**
806 * Works the THREADINT::cReadLocks member.
807 *
808 * @param Thread The current thread.
809 */
810RTDECL(void) RTLockValidatorReadLockInc(RTTHREAD Thread);
811
812/**
813 * Works the THREADINT::cReadLocks member.
814 *
815 * @param Thread The current thread.
816 */
817RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread);
818
819/**
820 * Query which lock the specified thread is waiting on.
821 *
822 * @returns The lock handle value or NULL.
823 * @param hThread The thread in question.
824 */
825RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread);
826
827/**
828 * Checks if the thread is running in the lock validator after it has entered a
829 * block state.
830 *
831 * @returns true if it is, false if it isn't.
832 * @param hThread The thread in question.
833 */
834RTDECL(bool) RTLockValidatorIsBlockedThreadInValidator(RTTHREAD hThread);
835
836
837
838/**
839 * Creates a new lock validator class, all properties specified.
840 *
841 * @returns IPRT status code
842 * @param phClass Where to return the class handle.
843 * @param pSrcPos The source position of the create call.
844 * @param fAutodidact Whether the class should be allowed to teach
845 * itself new locking order rules (true), or if the
846 * user will teach it all it needs to know (false).
847 * @param fRecursionOk Whether to allow lock recursion or not.
848 * @param fStrictReleaseOrder Enforce strict lock release order or not.
849 * @param cMsMinDeadlock Used to raise the sleep interval at which
850 * deadlock detection kicks in. Minimum is 1 ms,
851 * while RT_INDEFINITE_WAIT will disable it.
852 * @param cMsMinOrder Used to raise the sleep interval at which lock
853 * order validation kicks in. Minimum is 1 ms,
854 * while RT_INDEFINITE_WAIT will disable it.
855 * @param pszNameFmt Class name format string, optional (NULL). Max
856 * length is 32 bytes.
857 * @param ... Format string arguments.
858 *
859 * @remarks The properties can be modified after creation by the
860 * RTLockValidatorClassSet* methods.
861 */
862RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
863 bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
864 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
865 const char *pszNameFmt, ...);
866
867/**
868 * Creates a new lock validator class, all properties specified.
869 *
870 * @returns IPRT status code
871 * @param phClass Where to return the class handle.
872 * @param pSrcPos The source position of the create call.
873 * @param fAutodidact Whether the class should be allowed to teach
874 * itself new locking order rules (true), or if the
875 * user will teach it all it needs to know (false).
876 * @param fRecursionOk Whether to allow lock recursion or not.
877 * @param fStrictReleaseOrder Enforce strict lock release order or not.
878 * @param cMsMinDeadlock Used to raise the sleep interval at which
879 * deadlock detection kicks in. Minimum is 1 ms,
880 * while RT_INDEFINITE_WAIT will disable it.
881 * @param cMsMinOrder Used to raise the sleep interval at which lock
882 * order validation kicks in. Minimum is 1 ms,
883 * while RT_INDEFINITE_WAIT will disable it.
884 * @param pszNameFmt Class name format string, optional (NULL). Max
885 * length is 32 bytes.
886 * @param va Format string arguments.
887 *
888 * @remarks The properties can be modified after creation by the
889 * RTLockValidatorClassSet* methods.
890 */
891RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
892 bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
893 RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
894 const char *pszNameFmt, va_list va);
895
896/**
897 * Creates a new lock validator class.
898 *
899 * @returns IPRT status code
900 * @param phClass Where to return the class handle.
901 * @param fAutodidact Whether the class should be allowed to teach
902 * itself new locking order rules (true), or if the
903 * user will teach it all it needs to know (false).
904 * @param pszFile The source position of the call, file.
905 * @param iLine The source position of the call, line.
906 * @param pszFunction The source position of the call, function.
907 * @param pszNameFmt Class name format string, optional (NULL). Max
908 * length is 32 bytes.
909 * @param ... Format string arguments.
910 */
911RTDECL(int) RTLockValidatorClassCreate(PRTLOCKVALCLASS phClass, bool fAutodidact, RT_SRC_POS_DECL, const char *pszNameFmt, ...);
912
913/**
914 * Creates a new lock validator class with a reference that is consumed by the
915 * first call to RTLockValidatorClassRetain.
916 *
917 * This is tailored for use in the parameter list of a semaphore constructor.
918 *
919 * @returns Class handle with a reference that is automatically consumed by the
920 * first retainer. NIL_RTLOCKVALCLASS if we run into trouble.
921 *
922 * @param pszFile The source position of the call, file.
923 * @param iLine The source position of the call, line.
924 * @param pszFunction The source position of the call, function.
925 * @param pszNameFmt Class name format string, optional (NULL). Max
926 * length is 32 bytes.
927 * @param ... Format string arguments.
928 */
929RTDECL(RTLOCKVALCLASS) RTLockValidatorClassCreateUnique(RT_SRC_POS_DECL, const char *pszNameFmt, ...);
930
931/**
932 * Finds a class for the specified source position.
933 *
934 * @returns A handle to the class (not retained!) or NIL_RTLOCKVALCLASS.
935 * @param pSrcPos The source position.
936 */
937RTDECL(RTLOCKVALCLASS) RTLockValidatorClassFindForSrcPos(PRTLOCKVALSRCPOS pSrcPos);
938
939/**
940 * Finds or creates a class given the source position.
941 *
942 * @returns Class handle (not retained!) or NIL_RTLOCKVALCLASS.
943 * @param pszFile The source file.
944 * @param iLine The line in that source file.
945 * @param pszFunction The function name.
946 * @param pszNameFmt Class name format string, optional (NULL). Max
947 * length is 32 bytes.
948 * @param ... Format string arguments.
949 */
950RTDECL(RTLOCKVALCLASS) RTLockValidatorClassForSrcPos(RT_SRC_POS_DECL, const char *pszNameFmt, ...);
951
952/**
953 * Retains a reference to a lock validator class.
954 *
955 * @returns New reference count; UINT32_MAX if the handle is invalid.
956 * @param hClass Handle to the class.
957 */
958RTDECL(uint32_t) RTLockValidatorClassRetain(RTLOCKVALCLASS hClass);
959
960/**
961 * Releases a reference to a lock validator class.
962 *
963 * @returns New reference count. 0 if hClass is NIL_RTLOCKVALCLASS. UINT32_MAX
964 * if the handle is invalid.
965 * @param hClass Handle to the class.
966 */
967RTDECL(uint32_t) RTLockValidatorClassRelease(RTLOCKVALCLASS hClass);
968
969/**
970 * Teaches the class @a hClass that locks in the class @a hPriorClass can be
971 * held when taking a lock of class @hClass
972 *
973 * @returns IPRT status.
974 * @param hClass Handle to the pupil class.
975 * @param hPriorClass Handle to the class that can be held prior to
976 * taking a lock in the pupil class. (No reference
977 * is consumed.)
978 */
979RTDECL(int) RTLockValidatorClassAddPriorClass(RTLOCKVALCLASS hClass, RTLOCKVALCLASS hPriorClass);
980
981/**
982 * Enables or disables the strict release order enforcing.
983 *
984 * @returns IPRT status.
985 * @param hClass Handle to the class to change.
986 * @param fEnable Enable it (true) or disable it (false).
987 */
988RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled);
989
990/**
991 * Enables / disables the lock validator for new locks.
992 *
993 * @returns The old setting.
994 * @param fEnabled The new setting.
995 */
996RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled);
997
998/**
999 * Is the lock validator enabled?
1000 *
1001 * @returns True if enabled, false if not.
1002 */
1003RTDECL(bool) RTLockValidatorIsEnabled(void);
1004
1005/**
1006 * Controls whether the lock validator should be quiet or noisy (default).
1007 *
1008 * @returns The old setting.
1009 * @param fQuiet The new setting.
1010 */
1011RTDECL(bool) RTLockValidatorSetQuiet(bool fQuiet);
1012
1013/**
1014 * Is the lock validator quiet or noisy?
1015 *
1016 * @returns True if it is quiet, false if noisy.
1017 */
1018RTDECL(bool) RTLockValidatorIsQuiet(void);
1019
1020/**
1021 * Makes the lock validator panic (default) or not.
1022 *
1023 * @returns The old setting.
1024 * @param fPanic The new setting.
1025 */
1026RTDECL(bool) RTLockValidatorSetMayPanic(bool fPanic);
1027
1028/**
1029 * Can the lock validator cause panic.
1030 *
1031 * @returns True if it can, false if not.
1032 */
1033RTDECL(bool) RTLockValidatorMayPanic(void);
1034
1035
1036RT_C_DECLS_END
1037
1038/** @} */
1039
1040#endif
1041
1042
Note: See TracBrowser for help on using the repository browser.

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