VirtualBox

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

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

Raw conversion of semrw-lockless-generic.cpp into RTCritSectEx.

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