VirtualBox

source: vbox/trunk/include/iprt/critsect.h@ 25704

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

iprt,pdmcritsect: More flexible lock naming, added RTCritSectSetSubClass and made some RTCritSectInitEx.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.4 KB
Line 
1/** @file
2 * IPRT - Critical Sections.
3 */
4
5/*
6 * Copyright (C) 2006-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_critsect_h
31#define ___iprt_critsect_h
32
33#include <iprt/cdefs.h>
34#include <iprt/types.h>
35#include <iprt/assert.h>
36#ifdef IN_RING3
37# include <iprt/thread.h>
38#endif
39
40
41RT_C_DECLS_BEGIN
42
43/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
44 *
45 * "Critical section" synchronization primitives can be used to
46 * protect a section of code or data to which access must be exclusive;
47 * only one thread can hold access to a critical section at one time.
48 *
49 * A critical section is a fast recursive write lock; if the critical
50 * section is not acquired, then entering it is fast (requires no system
51 * call). IPRT uses the Windows terminology here; on other platform, this
52 * might be called a "futex" or a "fast mutex". As opposed to IPRT
53 * "fast mutexes" (see @ref grp_rt_sems_fast_mutex ), critical sections
54 * are recursive.
55 *
56 * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
57 * and RTCritSectLeave to acquire and release access.
58 *
59 * For an overview of all types of synchronization primitives provided
60 * by IPRT (event, mutex/fast mutex/read-write mutex semaphores), see
61 * @ref grp_rt_sems .
62 *
63 * @ingroup grp_rt
64 * @{
65 */
66
67/**
68 * Critical section.
69 */
70typedef struct RTCRITSECT
71{
72 /** Magic used to validate the section state.
73 * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
74 volatile uint32_t u32Magic;
75 /** Number of lockers.
76 * -1 if the section is free. */
77 volatile int32_t cLockers;
78 /** The owner thread. */
79 volatile RTNATIVETHREAD NativeThreadOwner;
80 /** Number of nested enter operations performed.
81 * Greater or equal to 1 if owned, 0 when free.
82 */
83 volatile int32_t cNestings;
84 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
85 uint32_t fFlags;
86 /** The semaphore to block on. */
87 RTSEMEVENT EventSem;
88 /** Lock validator record. Only used in strict builds. */
89 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
90 /** Alignmnet padding. */
91 RTHCPTR Alignment;
92} RTCRITSECT;
93AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
94/** Pointer to a critical section. */
95typedef RTCRITSECT *PRTCRITSECT;
96/** Pointer to a const critical section. */
97typedef const RTCRITSECT *PCRTCRITSECT;
98
99/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
100#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
101
102/** If set, nesting(/recursion) is not allowed. */
103#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
104/** Disables lock validation. */
105#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
106
107#ifdef IN_RING3
108
109/**
110 * Initialize a critical section.
111 */
112RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
113
114/**
115 * Initialize a critical section.
116 *
117 * @returns iprt status code.
118 * @param pCritSect Pointer to the critical section structure.
119 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
120 * \#defines.
121 * @param hClass The class (no reference consumed). If NIL, the
122 * no lock order validation will be performed on
123 * this lock.
124 * @param uSubClass The sub-class. This is used to define lock
125 * order inside the same class. If you don't know,
126 * then pass RTLOCKVAL_SUB_CLASS_NONE.
127 * @param pszNameFmt Name format string for the lock validator,
128 * optional (NULL). Max length is 32 bytes.
129 * @param ... Format string arguments.
130 */
131RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags,
132 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszName, ...);
133
134/**
135 * Changes the lock validator sub-class of the critical section.
136 *
137 * It is recommended to try make sure that nobody is using this critical section
138 * while changing the value.
139 *
140 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
141 * lock validator isn't compiled in or either of the parameters are
142 * invalid.
143 * @param pCritSect The critical section.
144 * @param uSubClass The new sub-class value.
145 */
146RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
147
148/**
149 * Enter a critical section.
150 *
151 * @returns VINF_SUCCESS on success.
152 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
153 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
154 * @param pCritSect The critical section.
155 */
156RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
157
158/**
159 * Enter a critical section.
160 *
161 * @retval VINF_SUCCESS on success.
162 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
163 * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
164 *
165 * @param pCritSect The critical section.
166 * @param uId Where we're entering the section.
167 * @param pszFile The source position - file.
168 * @param iLine The source position - line.
169 * @param pszFunction The source position - function.
170 */
171RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
172
173/**
174 * Try enter a critical section.
175 *
176 * @retval VINF_SUCCESS on success.
177 * @retval VERR_SEM_BUSY if the critsect was owned.
178 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
179 * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
180 *
181 * @param pCritSect The critical section.
182 */
183RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
184
185/**
186 * Try enter a critical section.
187 *
188 * @retval VINF_SUCCESS on success.
189 * @retval VERR_SEM_BUSY if the critsect was owned.
190 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
191 * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
192 *
193 * @param pCritSect The critical section.
194 * @param uId Where we're entering the section.
195 * @param pszFile The source position - file.
196 * @param iLine The source position - line.
197 * @param pszFunction The source position - function.
198 */
199RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
200
201/**
202 * Enter multiple critical sections.
203 *
204 * This function will enter ALL the specified critical sections before returning.
205 *
206 * @returns VINF_SUCCESS on success.
207 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
208 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
209 * @param cCritSects Number of critical sections in the array.
210 * @param papCritSects Array of critical section pointers.
211 *
212 * @remark Please note that this function will not necessarily come out favourable in a
213 * fight with other threads which are using the normal RTCritSectEnter() function.
214 * Therefore, avoid having to enter multiple critical sections!
215 */
216RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
217
218/**
219 * Enter multiple critical sections.
220 *
221 * This function will enter ALL the specified critical sections before returning.
222 *
223 * @returns VINF_SUCCESS on success.
224 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
225 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
226 *
227 * @param cCritSects Number of critical sections in the array.
228 * @param papCritSects Array of critical section pointers.
229 * @param uId Where we're entering the section.
230 * @param pszFile The source position - file.
231 * @param iLine The source position - line.
232 * @param pszFunction The source position - function.
233 *
234 * @remark See RTCritSectEnterMultiple().
235 */
236RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL);
237
238/**
239 * Leave a critical section.
240 *
241 * @returns VINF_SUCCESS.
242 * @param pCritSect The critical section.
243 */
244RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);
245
246/**
247 * Leave multiple critical sections.
248 *
249 * @returns VINF_SUCCESS.
250 * @param cCritSects Number of critical sections in the array.
251 * @param papCritSects Array of critical section pointers.
252 */
253RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
254
255/**
256 * Deletes a critical section.
257 *
258 * @returns VINF_SUCCESS.
259 * @param pCritSect The critical section.
260 */
261RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);
262
263/**
264 * Checks the caller is the owner of the critical section.
265 *
266 * @returns true if owner.
267 * @returns false if not owner.
268 * @param pCritSect The critical section.
269 */
270DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
271{
272 return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
273}
274
275#endif /* IN_RING3 */
276
277/**
278 * Checks the section is owned by anyone.
279 *
280 * @returns true if owned.
281 * @returns false if not owned.
282 * @param pCritSect The critical section.
283 */
284DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
285{
286 return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
287}
288
289/**
290 * Gets the thread id of the critical section owner.
291 *
292 * @returns Thread id of the owner thread if owned.
293 * @returns NIL_RTNATIVETHREAD is not owned.
294 * @param pCritSect The critical section.
295 */
296DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
297{
298 return pCritSect->NativeThreadOwner;
299}
300
301/**
302 * Checks if a critical section is initialized or not.
303 *
304 * @returns true if initialized.
305 * @returns false if not initialized.
306 * @param pCritSect The critical section.
307 */
308DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
309{
310 return pCritSect->u32Magic == RTCRITSECT_MAGIC;
311}
312
313/**
314 * Gets the recursion depth.
315 *
316 * @returns The recursion depth.
317 * @param pCritSect The Critical section
318 */
319DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
320{
321 return pCritSect->cNestings;
322}
323
324/**
325 * Gets the waiter count
326 *
327 * @returns The waiter count
328 * @param pCritSect The Critical section
329 */
330DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
331{
332 return pCritSect->cLockers;
333}
334
335/* Strict build: Remap the three enter calls to the debug versions. */
336#ifdef RT_STRICT
337# ifdef ___iprt_asm_h
338# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
339# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
340# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
341# else
342# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS)
343# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS)
344# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 0, RT_SRC_POS)
345# endif
346#endif
347
348/** @} */
349
350RT_C_DECLS_END
351
352#endif
353
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