VirtualBox

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

Last change on this file since 25475 was 25467, checked in by vboxsync, 15 years ago

IPRT,PDMCritSect: More lock validation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 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
38
39/** @defgroup grp_ldr RTLockValidator - Lock Validator
40 * @ingroup grp_rt
41 * @{
42 */
43
44RT_C_DECLS_BEGIN
45
46/**
47 * Record recording the ownership of a lock.
48 *
49 * This is typically part of the per-lock data structure when compiling with
50 * the lock validator.
51 */
52typedef struct RTLOCKVALIDATORREC
53{
54 /** Magic value (RTLOCKVALIDATORREC_MAGIC). */
55 uint32_t u32Magic;
56 /** The line number in the file. */
57 uint32_t volatile uLine;
58 /** The file where the lock was taken. */
59 R3R0PTRTYPE(const char * volatile) pszFile;
60 /** The function where the lock was taken. */
61 R3R0PTRTYPE(const char * volatile) pszFunction;
62 /** Some ID indicating where the lock was taken, typically an address. */
63 RTHCUINTPTR volatile uId;
64 /** The current owner thread. */
65 RTTHREAD volatile hThread;
66 /** Pointer to the lock record below us. Only accessed by the owner. */
67 R3R0PTRTYPE(PRTLOCKVALIDATORREC) pDown;
68 /** Recursion count */
69 uint32_t cRecursion;
70 /** The lock sub-class. */
71 uint32_t volatile uSubClass;
72 /** The lock class. */
73 RTLOCKVALIDATORCLASS hClass;
74 /** Pointer to the lock. */
75 RTHCPTR hLock;
76 /** The lock name. */
77 R3R0PTRTYPE(const char *) pszName;
78} RTLOCKVALIDATORREC;
79AssertCompileSize(RTLOCKVALIDATORREC, HC_ARCH_BITS == 32 ? 48 : 80);
80/* The pointer is defined in iprt/types.h */
81
82
83/** @name Special sub-class values.
84 * The range 16..UINT32_MAX is available to the user, the range 0..15 is
85 * reserved for the lock validator.
86 * @{ */
87/** Not allowed to be taken with any other locks in the same class.
88 * This is the recommended value. */
89#define RTLOCKVALIDATOR_SUB_CLASS_NONE UINT32_C(0)
90/** Any order is allowed within the class. */
91#define RTLOCKVALIDATOR_SUB_CLASS_ANY UINT32_C(1)
92/** The first user value. */
93#define RTLOCKVALIDATOR_SUB_CLASS_USER UINT32_C(16)
94/** @} */
95
96/**
97 * Initialize a lock validator record.
98 *
99 * Use RTLockValidatorDelete to deinitialize it.
100 *
101 * @param pRec The record.
102 * @param hClass The class. If NIL, the no lock order
103 * validation will be performed on this lock.
104 * @param uSubClass The sub-class. This is used to define lock
105 * order inside the same class. If you don't know,
106 * then pass RTLOCKVALIDATOR_SUB_CLASS_NONE.
107 * @param pszName The lock name (optional).
108 * @param hLock The lock handle.
109 */
110RTDECL(void) RTLockValidatorInit(PRTLOCKVALIDATORREC pRec, RTLOCKVALIDATORCLASS hClass,
111 uint32_t uSubClass, const char *pszName, void *hLock);
112/**
113 * Uninitialize a lock validator record previously initialized by
114 * RTLockValidatorInit.
115 *
116 * @param pRec The record. Must be valid.
117 */
118RTDECL(void) RTLockValidatorDelete(PRTLOCKVALIDATORREC pRec);
119
120/**
121 * Create and initialize a lock validator record.
122 *
123 * Use RTLockValidatorDestroy to deinitialize and destroy the returned record.
124 *
125 * @return VINF_SUCCESS or VERR_NO_MEMORY.
126 * @param ppRec Where to return the record pointer.
127 * @param hClass The class. If NIL, the no lock order
128 * validation will be performed on this lock.
129 * @param uSubClass The sub-class. This is used to define lock
130 * order inside the same class. If you don't know,
131 * then pass RTLOCKVALIDATOR_SUB_CLASS_NONE.
132 * @param pszName The lock name (optional).
133 * @param hLock The lock handle.
134 */
135RTDECL(int) RTLockValidatorCreate(PRTLOCKVALIDATORREC *ppRec, RTLOCKVALIDATORCLASS hClass,
136 uint32_t uSubClass, const char *pszName, void *hLock);
137
138/**
139 * Deinitialize and destroy a record created by RTLockValidatorCreate.
140 *
141 * @param ppRec Pointer to the record pointer. Will be set to
142 * NULL.
143 */
144RTDECL(void) RTLockValidatorDestroy(PRTLOCKVALIDATORREC *ppRec);
145
146/**
147 * Check the locking order.
148 *
149 * This is called by routines implementing lock acquisition.
150 *
151 * @retval VINF_SUCCESS on success.
152 * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all
153 * necessary whining and breakpointing before returning.
154 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
155 *
156 * @param pRec The validator record.
157 * @param hThread The handle of the calling thread. If not known,
158 * pass NIL_RTTHREAD and this method will figure it
159 * out.
160 * @param uId Some kind of locking location ID. Typically a
161 * return address up the stack. Optional (0).
162 * @param pszFile The file where the lock is being acquired from.
163 * Optional.
164 * @param iLine The line number in that file. Optional (0).
165 * @param pszFunction The functionn where the lock is being acquired
166 * from. Optional.
167 */
168RTDECL(int) RTLockValidatorCheckOrder(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, RTHCUINTPTR uId, RT_SRC_POS_DECL);
169
170/**
171 * Change the thread state to blocking and do deadlock detection.
172 *
173 * @retval VINF_SUCCESS
174 * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the
175 * motions.
176 * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is
177 * already the owner. Gone thru the motions.
178 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
179 *
180 * @param pRec The validator record we're blocing on.
181 * @param hThread The current thread. Shall not be NIL_RTTHREAD!
182 * @param enmState The sleep state.
183 * @param pvBlock Pointer to a RTLOCKVALIDATORREC structure.
184 * @param fRecursiveOk Whether it's ok to recurse.
185 * @param uId Where we are blocking.
186 * @param RT_SRC_POS_DECL Where we are blocking.
187 */
188RTDECL(int) RTLockValidatorCheckBlocking(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread,
189 RTTHREADSTATE enmState, bool fRecursiveOk,
190 RTHCUINTPTR uId, RT_SRC_POS_DECL);
191
192/**
193 * Check the exit order.
194 *
195 * This is called by routines implementing releasing the lock.
196 *
197 * @retval VINF_SUCCESS on success.
198 * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have
199 * done all necessary whining and breakpointing before returning.
200 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
201 *
202 * @param pRec The validator record.
203 */
204RTDECL(int) RTLockValidatorCheckReleaseOrder(PRTLOCKVALIDATORREC pRec);
205
206/**
207 * Checks and records a lock recursion.
208 *
209 * @retval VINF_SUCCESS on success.
210 * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone
211 * thru the motions.
212 * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid.
213 *
214 * @param pRec The validator record.
215 * @param uId Some kind of locking location ID. Typically a
216 * return address up the stack. Optional (0).
217 * @param pszFile The file where the lock is being acquired from.
218 * Optional.
219 * @param iLine The line number in that file. Optional (0).
220 * @param pszFunction The functionn where the lock is being acquired
221 * from. Optional.
222 */
223RTDECL(int) RTLockValidatorRecordRecursion(PRTLOCKVALIDATORREC pRec, RTHCUINTPTR uId, RT_SRC_POS_DECL);
224
225/**
226 * Records a lock unwind (releasing one recursion).
227 *
228 * This should be coupled with called to RTLockValidatorRecordRecursion.
229 *
230 * @param pRec The validator record.
231 */
232RTDECL(void) RTLockValidatorRecordUnwind(PRTLOCKVALIDATORREC pRec);
233
234/**
235 * Record the specified thread as lock owner and increment the write lock count.
236 *
237 * This function is typically called after acquiring the lock.
238 *
239 * @returns hThread resolved. Can return NIL_RTHREAD iff we fail to adopt the
240 * alien thread or if pRec is invalid.
241 *
242 * @param pRec The validator record.
243 * @param hThread The handle of the calling thread. If not known,
244 * pass NIL_RTTHREAD and this method will figure it
245 * out.
246 * @param uId Some kind of locking location ID. Typically a
247 * return address up the stack. Optional (0).
248 * @param pszFile The file where the lock is being acquired from.
249 * Optional.
250 * @param iLine The line number in that file. Optional (0).
251 * @param pszFunction The functionn where the lock is being acquired
252 * from. Optional.
253 */
254RTDECL(RTTHREAD) RTLockValidatorSetOwner(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, RTHCUINTPTR uId, RT_SRC_POS_DECL);
255
256
257/**
258 * Clear the lock ownership and decrement the write lock count.
259 *
260 * This is typically called before release the lock.
261 *
262 * @returns The thread handle of the previous owner. NIL_RTTHREAD if the record
263 * is invalid or didn't have any owner.
264 * @param pRec The validator record.
265 */
266RTDECL(RTTHREAD) RTLockValidatorUnsetOwner(PRTLOCKVALIDATORREC pRec);
267
268/**
269 * Gets the number of write locks and critical sections the specified
270 * thread owns.
271 *
272 * This number does not include any nested lock/critect entries.
273 *
274 * Note that it probably will return 0 for non-strict builds since
275 * release builds doesn't do unnecessary diagnostic counting like this.
276 *
277 * @returns Number of locks on success (0+) and VERR_INVALID_HANDLER on failure
278 * @param Thread The thread we're inquiring about.
279 * @remarks Will only work for strict builds.
280 */
281RTDECL(int32_t) RTLockValidatorWriteLockGetCount(RTTHREAD Thread);
282
283/**
284 * Works the THREADINT::cWriteLocks member, mostly internal.
285 *
286 * @param Thread The current thread.
287 */
288RTDECL(void) RTLockValidatorWriteLockInc(RTTHREAD Thread);
289
290/**
291 * Works the THREADINT::cWriteLocks member, mostly internal.
292 *
293 * @param Thread The current thread.
294 */
295RTDECL(void) RTLockValidatorWriteLockDec(RTTHREAD Thread);
296
297/**
298 * Gets the number of read locks the specified thread owns.
299 *
300 * Note that nesting read lock entry will be included in the
301 * total sum. And that it probably will return 0 for non-strict
302 * builds since release builds doesn't do unnecessary diagnostic
303 * counting like this.
304 *
305 * @returns Number of read locks on success (0+) and VERR_INVALID_HANDLER on failure
306 * @param Thread The thread we're inquiring about.
307 */
308RTDECL(int32_t) RTLockValidatorReadLockGetCount(RTTHREAD Thread);
309
310/**
311 * Works the THREADINT::cReadLocks member.
312 *
313 * @param Thread The current thread.
314 */
315RTDECL(void) RTLockValidatorReadLockInc(RTTHREAD Thread);
316
317/**
318 * Works the THREADINT::cReadLocks member.
319 *
320 * @param Thread The current thread.
321 */
322RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread);
323
324
325
326/*RTDECL(int) RTLockValidatorClassCreate();*/
327
328
329RT_C_DECLS_END
330
331/** @} */
332
333#endif
334
335
Note: See TracBrowser for help on using the repository browser.

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