VirtualBox

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

Last change on this file since 51940 was 51940, checked in by vboxsync, 10 years ago

GMMR0: Switched from fast mutex to critical section for the giant GMMR0 lock to avoid running into unnecessary trouble with the windows driver verifier. Required making the critical section code compile and link in the ring-0 environment.

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