VirtualBox

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

Last change on this file since 45903 was 45151, checked in by vboxsync, 12 years ago

iprt/critsect.h: Cleanups (R/W mostly).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.7 KB
Line 
1/** @file
2 * IPRT - Critical Sections.
3 */
4
5/*
6 * Copyright (C) 2006-2013 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/** If set, the critical section becomes a dummy that doesn't serialize any
105 * threads. This flag can only be set at creation time.
106 *
107 * The intended use is avoiding lots of conditional code where some component
108 * might or might not require entering a critical section before access. */
109#define RTCRITSECT_FLAGS_NOP UINT32_C(0x00000008)
110/** @} */
111
112
113#ifdef IN_RING3
114
115/**
116 * Initialize a critical section.
117 */
118RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
119
120/**
121 * Initialize a critical section.
122 *
123 * @returns iprt status code.
124 * @param pCritSect Pointer to the critical section structure.
125 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
126 * \#defines.
127 * @param hClass The class (no reference consumed). If NIL, no lock
128 * order validation will be performed on this lock.
129 * @param uSubClass The sub-class. This is used to define lock order
130 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
131 * recommended value here.
132 * @param pszNameFmt Name format string for the lock validator, optional
133 * (NULL). Max length is 32 bytes.
134 * @param ... Format string arguments.
135 */
136RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags,
137 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...);
138
139/**
140 * Changes the lock validator sub-class of the critical section.
141 *
142 * It is recommended to try make sure that nobody is using this critical section
143 * while changing the value.
144 *
145 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
146 * lock validator isn't compiled in or either of the parameters are
147 * invalid.
148 * @param pCritSect The critical section.
149 * @param uSubClass The new sub-class value.
150 */
151RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
152
153/**
154 * Enter a critical section.
155 *
156 * @returns VINF_SUCCESS on success.
157 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
158 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
159 * during the operation.
160 * @param pCritSect The critical section.
161 */
162RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
163
164/**
165 * Enter a critical section.
166 *
167 * @returns IPRT status code.
168 * @retval VINF_SUCCESS on success.
169 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
170 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
171 * during the operation.
172 *
173 * @param pCritSect The critical section.
174 * @param uId Where we're entering the section.
175 * @param pszFile The source position - file.
176 * @param iLine The source position - line.
177 * @param pszFunction The source position - function.
178 */
179RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
180
181/**
182 * Try enter a critical section.
183 *
184 * @retval VINF_SUCCESS on success.
185 * @retval VERR_SEM_BUSY if the critsect was owned.
186 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
187 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
188 * during the operation.
189 *
190 * @param pCritSect The critical section.
191 */
192RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
193
194/**
195 * Try enter a critical section.
196 *
197 * @retval VINF_SUCCESS on success.
198 * @retval VERR_SEM_BUSY if the critsect was owned.
199 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
200 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
201 * during the operation.
202 *
203 * @param pCritSect The critical section.
204 * @param uId Where we're entering the section.
205 * @param pszFile The source position - file.
206 * @param iLine The source position - line.
207 * @param pszFunction The source position - function.
208 */
209RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
210
211/**
212 * Enter multiple critical sections.
213 *
214 * This function will enter ALL the specified critical sections before returning.
215 *
216 * @returns VINF_SUCCESS on success.
217 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
218 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
219 * during the operation.
220 * @param cCritSects Number of critical sections in the array.
221 * @param papCritSects Array of critical section pointers.
222 *
223 * @remark Please note that this function will not necessarily come out favourable in a
224 * fight with other threads which are using the normal RTCritSectEnter() function.
225 * Therefore, avoid having to enter multiple critical sections!
226 */
227RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
228
229/**
230 * Enter multiple critical sections.
231 *
232 * This function will enter ALL the specified critical sections before returning.
233 *
234 * @returns VINF_SUCCESS on success.
235 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
236 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
237 * during the operation.
238 *
239 * @param cCritSects Number of critical sections in the array.
240 * @param papCritSects Array of critical section pointers.
241 * @param uId Where we're entering the section.
242 * @param pszFile The source position - file.
243 * @param iLine The source position - line.
244 * @param pszFunction The source position - function.
245 *
246 * @remark See RTCritSectEnterMultiple().
247 */
248RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL);
249
250/**
251 * Leave a critical section.
252 *
253 * @returns VINF_SUCCESS.
254 * @param pCritSect The critical section.
255 */
256RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);
257
258/**
259 * Leave multiple critical sections.
260 *
261 * @returns VINF_SUCCESS.
262 * @param cCritSects Number of critical sections in the array.
263 * @param papCritSects Array of critical section pointers.
264 */
265RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
266
267/**
268 * Deletes a critical section.
269 *
270 * @returns VINF_SUCCESS.
271 * @param pCritSect The critical section.
272 */
273RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);
274
275/**
276 * Checks the caller is the owner of the critical section.
277 *
278 * @returns true if owner.
279 * @returns false if not owner.
280 * @param pCritSect The critical section.
281 */
282DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
283{
284 return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
285}
286
287#endif /* IN_RING3 */
288
289/**
290 * Checks the section is owned by anyone.
291 *
292 * @returns true if owned.
293 * @returns false if not owned.
294 * @param pCritSect The critical section.
295 */
296DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
297{
298 return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
299}
300
301/**
302 * Gets the thread id of the critical section owner.
303 *
304 * @returns Thread id of the owner thread if owned.
305 * @returns NIL_RTNATIVETHREAD is not owned.
306 * @param pCritSect The critical section.
307 */
308DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
309{
310 return pCritSect->NativeThreadOwner;
311}
312
313/**
314 * Checks if a critical section is initialized or not.
315 *
316 * @returns true if initialized.
317 * @returns false if not initialized.
318 * @param pCritSect The critical section.
319 */
320DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
321{
322 return pCritSect->u32Magic == RTCRITSECT_MAGIC;
323}
324
325/**
326 * Gets the recursion depth.
327 *
328 * @returns The recursion depth.
329 * @param pCritSect The Critical section
330 */
331DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
332{
333 return pCritSect->cNestings;
334}
335
336/**
337 * Gets the waiter count
338 *
339 * @returns The waiter count
340 * @param pCritSect The Critical section
341 */
342DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
343{
344 return pCritSect->cLockers;
345}
346
347/* Lock strict build: Remap the three enter calls to the debug versions. */
348#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
349# ifdef ___iprt_asm_h
350# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
351# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
352# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
353# else
354# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS)
355# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS)
356# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 0, RT_SRC_POS)
357# endif
358#endif
359
360/* Strict lock order: Automatically classify locks by init location. */
361#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
362# define RTCritSectInit(pCritSect) \
363 RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
364 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
365 RTLOCKVAL_SUB_CLASS_NONE, NULL)
366#endif
367
368/** @} */
369
370
371
372/** @defgroup grp_rt_critsectrw RTCritSectRw - Read/Write Critical Sections
373 * @ingroup grp_rt
374 * @{
375 */
376
377/**
378 * Read/write critical section.
379 */
380typedef struct RTCRITSECTRW
381{
382 /** Magic used to validate the section state.
383 * RTCRITSECTRW_MAGIC is the value of an initialized & operational section. */
384 volatile uint32_t u32Magic;
385
386 /** Indicates whether hEvtRead needs resetting. */
387 bool volatile fNeedReset;
388 /** Explicit alignment padding. */
389 bool volatile afPadding[1];
390 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
391 uint16_t fFlags;
392
393 /** The state variable.
394 * All accesses are atomic and it bits are defined like this:
395 * Bits 0..14 - cReads.
396 * Bit 15 - Unused.
397 * Bits 16..31 - cWrites. - doesn't make sense here
398 * Bit 31 - fDirection; 0=Read, 1=Write.
399 * Bits 32..46 - cWaitingReads
400 * Bit 47 - Unused.
401 * Bits 48..62 - cWaitingWrites
402 * Bit 63 - Unused.
403 */
404 uint64_t volatile u64State;
405 /** The write owner. */
406 RTNATIVETHREAD volatile hNativeWriter;
407 /** The number of reads made by the current writer. */
408 uint32_t volatile cWriterReads;
409 /** The number of recursions made by the current writer. (The initial grabbing
410 * of the lock counts as the first one.) */
411 uint32_t volatile cWriteRecursions;
412
413 /** What the writer threads are blocking on. */
414 RTSEMEVENT hEvtWrite;
415 /** What the read threads are blocking on when waiting for the writer to
416 * finish. */
417 RTSEMEVENTMULTI hEvtRead;
418
419 /** The validator record for the writer. */
420 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorWrite;
421 /** The validator record for the readers. */
422 R3R0PTRTYPE(PRTLOCKVALRECSHRD) pValidatorRead;
423#if HC_ARCH_BITS == 32
424 /** Size padding. */
425 RTHCPTR HCPtrPadding;
426#endif
427} RTCRITSECTRW;
428AssertCompileSize(RTCRITSECTRW, HC_ARCH_BITS == 32 ? 48 : 64);
429
430/** RTCRITSECTRW::u32Magic value. (Eric Allan Dolphy, Jr.) */
431#define RTCRITSECTRW_MAGIC UINT32_C(0x19280620)
432/** RTCRITSECTRW::u32Magic dead value. */
433#define RTCRITSECTRW_MAGIC_DEAD UINT32_C(0x19640629)
434
435/** @name RTCRITSECTRW::u64State values.
436 * @note Using RTCSRW instead of RTCRITSECTRW to save space.
437 * @{ */
438#define RTCSRW_CNT_BITS 15
439#define RTCSRW_CNT_MASK UINT64_C(0x00007fff)
440
441#define RTCSRW_CNT_RD_SHIFT 0
442#define RTCSRW_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_RD_SHIFT)
443#define RTCSRW_CNT_WR_SHIFT 16
444#define RTCSRW_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_WR_SHIFT)
445
446#define RTCSRW_DIR_SHIFT 31
447#define RTCSRW_DIR_MASK RT_BIT_64(RTCSRW_DIR_SHIFT)
448#define RTCSRW_DIR_READ UINT64_C(0)
449#define RTCSRW_DIR_WRITE UINT64_C(1)
450
451#define RTCSRW_WAIT_CNT_RD_SHIFT 32
452#define RTCSRW_WAIT_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_RD_SHIFT)
453/* #define RTCSRW_WAIT_CNT_WR_SHIFT 48 */
454/* #define RTCSRW_WAIT_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_WR_SHIFT) */
455/** @} */
456
457#ifdef IN_RING3
458
459/**
460 * Initialize a critical section.
461 */
462RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
463
464/**
465 * Initialize a critical section.
466 *
467 * @returns IPRT status code.
468 * @param pThis Pointer to the read/write critical section.
469 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
470 * \#defines.
471 * @param hClass The class (no reference consumed). If NIL, no lock
472 * order validation will be performed on this lock.
473 * @param uSubClass The sub-class. This is used to define lock order
474 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
475 * recommended value here.
476 * @param pszNameFmt Name format string for the lock validator, optional
477 * (NULL). Max length is 32 bytes.
478 * @param ... Format string arguments.
479 */
480RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags,
481 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...);
482
483/**
484 * Changes the lock validator sub-class of the critical section.
485 *
486 * It is recommended to try make sure that nobody is using this critical section
487 * while changing the value.
488 *
489 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
490 * lock validator isn't compiled in or either of the parameters are
491 * invalid.
492 * @param pThis Pointer to the read/write critical section.
493 * @param uSubClass The new sub-class value.
494 */
495RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
496
497
498/**
499 * Enter a critical section with shared (read) access.
500 *
501 * @returns IPRT status code.
502 * @retval VINF_SUCCESS on success.
503 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
504 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
505 * during the operation.
506 * @param pThis Pointer to the read/write critical section.
507 */
508RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
509
510/**
511 * Enter a critical section with shared (read) access.
512 *
513 * @returns IPRT status code.
514 * @retval VINF_SUCCESS on success.
515 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
516 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
517 * during the operation.
518 *
519 * @param pThis Pointer to the read/write critical section.
520 * @param uId Where we're entering the section.
521 * @param pszFile The source position - file.
522 * @param iLine The source position - line.
523 * @param pszFunction The source position - function.
524 */
525RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
526
527/**
528 * Try enter a critical section with shared (read) access.
529 *
530 * @returns IPRT status code.
531 * @retval VINF_SUCCESS on success.
532 * @retval VERR_SEM_BUSY if the critsect was owned.
533 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
534 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
535 * during the operation.
536 *
537 * @param pThis Pointer to the read/write critical section.
538 */
539RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
540
541/**
542 * Try enter a critical section with shared (read) access.
543 *
544 * @returns IPRT status code.
545 * @retval VINF_SUCCESS on success.
546 * @retval VERR_SEM_BUSY if the critsect was owned.
547 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
548 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
549 * during the operation.
550 *
551 * @param pThis Pointer to the read/write critical section.
552 * @param uId Where we're entering the section.
553 * @param pszFile The source position - file.
554 * @param iLine The source position - line.
555 * @param pszFunction The source position - function.
556 */
557RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
558
559/**
560 * Leave a critical section held with shared access.
561 *
562 * @returns IPRT status code.
563 * @param pThis Pointer to the read/write critical section.
564 */
565RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
566
567
568/**
569 * Enter a critical section with exclusive (write) access.
570 *
571 * @returns IPRT status code.
572 * @retval VINF_SUCCESS on success.
573 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
574 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
575 * during the operation.
576 * @param pThis Pointer to the read/write critical section.
577 */
578RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
579
580/**
581 * Enter a critical section with exclusive (write) access.
582 *
583 * @retval VINF_SUCCESS on success.
584 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
585 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
586 * during the operation.
587 *
588 * @param pThis Pointer to the read/write critical section.
589 * @param uId Where we're entering the section.
590 * @param pszFile The source position - file.
591 * @param iLine The source position - line.
592 * @param pszFunction The source position - function.
593 */
594RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
595
596/**
597 * Try enter a critical section with exclusive (write) access.
598 *
599 * @returns IPRT status code.
600 * @retval VINF_SUCCESS on success.
601 * @retval VERR_SEM_BUSY if the critsect was owned.
602 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
603 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
604 * during the operation.
605 *
606 * @param pThis Pointer to the read/write critical section.
607 */
608RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
609
610/**
611 * Try enter a critical section with exclusive (write) access.
612 *
613 * @returns IPRT status code.
614 * @retval VINF_SUCCESS on success.
615 * @retval VERR_SEM_BUSY if the critsect was owned.
616 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
617 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
618 * during the operation.
619 *
620 * @param pThis Pointer to the read/write critical section.
621 * @param uId Where we're entering the section.
622 * @param pszFile The source position - file.
623 * @param iLine The source position - line.
624 * @param pszFunction The source position - function.
625 */
626RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
627
628/**
629 * Leave a critical section held exclusively.
630 *
631 * @returns IPRT status code; VINF_SUCCESS, VERR_NOT_OWNER, VERR_SEM_DESTROYED,
632 * or VERR_WRONG_ORDER.
633 * @param pThis Pointer to the read/write critical section.
634 */
635RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
636
637
638/**
639 * Deletes a critical section.
640 *
641 * @returns VINF_SUCCESS.
642 * @param pThis Pointer to the read/write critical section.
643 */
644RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
645
646/**
647 * Checks the caller is the exclusive (write) owner of the critical section.
648 *
649 * @retval @c true if owner.
650 * @retval @c false if not owner.
651 * @param pThis Pointer to the read/write critical section.
652 */
653RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
654
655/**
656 * Checks if the caller is one of the read owners of the critical section.
657 *
658 * @note !CAUTION! This API doesn't work reliably if lock validation isn't
659 * enabled. Meaning, the answer is not trustworhty unless
660 * RT_LOCK_STRICT or RTCRITSECTRW_STRICT was defined at build time.
661 * Also, make sure you do not use RTCRITSECTRW_FLAGS_NO_LOCK_VAL when
662 * creating the semaphore. And finally, if you used a locking class,
663 * don't disable deadlock detection by setting cMsMinDeadlock to
664 * RT_INDEFINITE_WAIT.
665 *
666 * In short, only use this for assertions.
667 *
668 * @returns @c true if reader, @c false if not.
669 * @param pThis Pointer to the read/write critical section.
670 * @param fWannaHear What you'd like to hear when lock validation is not
671 * available. (For avoiding asserting all over the
672 * place.)
673 */
674RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
675
676/**
677 * Gets the write recursion count.
678 *
679 * @returns The write recursion count (0 if bad critsect).
680 * @param pThis Pointer to the read/write critical section.
681 */
682RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
683
684/**
685 * Gets the read recursion count of the current writer.
686 *
687 * @returns The read recursion count (0 if bad critsect).
688 * @param pThis Pointer to the read/write critical section.
689 */
690RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
691
692/**
693 * Gets the current number of reads.
694 *
695 * This includes all read recursions, so it might be higher than the number of
696 * read owners. It does not include reads done by the current writer.
697 *
698 * @returns The read count (0 if bad critsect).
699 * @param pThis Pointer to the read/write critical section.
700 */
701RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
702
703#endif /* IN_RING3 */
704
705/**
706 * Checks if a critical section is initialized or not.
707 *
708 * @retval @c true if initialized.
709 * @retval @c false if not initialized.
710 * @param pThis Pointer to the read/write critical section.
711 */
712DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
713{
714 return pThis->u32Magic == RTCRITSECTRW_MAGIC;
715}
716
717/* Lock strict build: Remap the three enter calls to the debug versions. */
718#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
719# ifdef ___iprt_asm_h
720# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
721# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
722# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
723# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
724# else
725# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, 0, RT_SRC_POS)
726# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, 0, RT_SRC_POS)
727# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, 0, RT_SRC_POS)
728# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, 0, RT_SRC_POS)
729# endif
730#endif
731
732/* Strict lock order: Automatically classify locks by init location. */
733#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
734# define RTCritSectRwInit(a_pThis) \
735 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
736 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
737 RTLOCKVAL_SUB_CLASS_NONE, NULL)
738#endif
739
740/** @} */
741
742RT_C_DECLS_END
743
744#endif
745
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