VirtualBox

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

Last change on this file since 34575 was 33269, checked in by vboxsync, 14 years ago

IPRT: A quick replacement of the RTMemPage* and RTMemExec* APIs on posix. (Turned out to be a bit more work than expected because of the electric fence heap and init dependencies.)

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