VirtualBox

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

Last change on this file since 94719 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.3 KB
Line 
1/** @file
2 * IPRT - Critical Sections.
3 */
4
5/*
6 * Copyright (C) 2006-2022 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_INCLUDED_critsect_h
27#define IPRT_INCLUDED_critsect_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/cdefs.h>
33#include <iprt/types.h>
34#include <iprt/assert.h>
35#if defined(IN_RING3) || defined(IN_RING0)
36# include <iprt/thread.h>
37#endif
38#ifdef RT_LOCK_STRICT_ORDER
39# include <iprt/lockvalidator.h>
40#endif
41
42RT_C_DECLS_BEGIN
43
44/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
45 *
46 * "Critical section" synchronization primitives can be used to
47 * protect a section of code or data to which access must be exclusive;
48 * only one thread can hold access to a critical section at one time.
49 *
50 * A critical section is a fast recursive write lock; if the critical
51 * section is not acquired, then entering it is fast (requires no system
52 * call). IPRT uses the Windows terminology here; on other platform, this
53 * might be called a "futex" or a "fast mutex". As opposed to IPRT
54 * "fast mutexes" (see @ref grp_rt_sems_fast_mutex ), critical sections
55 * are recursive.
56 *
57 * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
58 * and RTCritSectLeave to acquire and release access.
59 *
60 * For an overview of all types of synchronization primitives provided
61 * by IPRT (event, mutex/fast mutex/read-write mutex semaphores), see
62 * @ref grp_rt_sems .
63 *
64 * @ingroup grp_rt
65 * @{
66 */
67
68/**
69 * Critical section.
70 */
71typedef struct RTCRITSECT
72{
73 /** Magic used to validate the section state.
74 * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
75 volatile uint32_t u32Magic;
76 /** Number of lockers.
77 * -1 if the section is free. */
78 volatile int32_t cLockers;
79 /** The owner thread. */
80 volatile RTNATIVETHREAD NativeThreadOwner;
81 /** Number of nested enter operations performed.
82 * Greater or equal to 1 if owned, 0 when free.
83 */
84 volatile int32_t cNestings;
85 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
86 uint32_t fFlags;
87 /** The semaphore to block on. */
88 RTSEMEVENT EventSem;
89 /** Lock validator record. Only used in strict builds. */
90 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
91 /** Alignment padding. */
92 RTHCPTR Alignment;
93} RTCRITSECT;
94AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
95
96/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
97#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
98
99/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags
100 * @{ */
101/** If set, nesting(/recursion) is not allowed. */
102#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
103/** Disables lock validation. */
104#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
105/** Bootstrap hack for use with certain memory allocator locks only! */
106#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
107/** If set, the critical section becomes a dummy that doesn't serialize any
108 * threads. This flag can only be set at creation time.
109 *
110 * The intended use is avoiding lots of conditional code where some component
111 * might or might not require entering a critical section before access. */
112#define RTCRITSECT_FLAGS_NOP UINT32_C(0x00000008)
113/** Indicates that this is a ring-0 critical section. */
114#define RTCRITSECT_FLAGS_RING0 UINT32_C(0x00000010)
115/** @} */
116
117
118#if defined(IN_RING3) || defined(IN_RING0)
119
120/**
121 * Initialize a critical section.
122 */
123RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
124
125/**
126 * Initialize a critical section.
127 *
128 * @returns iprt status code.
129 * @param pCritSect Pointer to the critical section structure.
130 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
131 * \#defines.
132 * @param hClass The class (no reference consumed). If NIL, no lock
133 * order validation will be performed on this lock.
134 * @param uSubClass The sub-class. This is used to define lock order
135 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
136 * recommended value here.
137 * @param pszNameFmt Name format string for the lock validator, optional
138 * (NULL). Max length is 32 bytes.
139 * @param ... Format string arguments.
140 */
141RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
142 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
143
144/**
145 * Changes the lock validator sub-class of the critical section.
146 *
147 * It is recommended to try make sure that nobody is using this critical section
148 * while changing the value.
149 *
150 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
151 * lock validator isn't compiled in or either of the parameters are
152 * invalid.
153 * @param pCritSect The critical section.
154 * @param uSubClass The new sub-class value.
155 */
156RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
157
158/**
159 * Enter a critical section.
160 *
161 * @returns VINF_SUCCESS on success.
162 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
163 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
164 * during the operation.
165 * @param pCritSect The critical section.
166 */
167RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
168
169/**
170 * Enter a critical section.
171 *
172 * @returns IPRT status code.
173 * @retval VINF_SUCCESS on success.
174 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
175 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
176 * during the operation.
177 *
178 * @param pCritSect The critical section.
179 * @param uId Where we're entering the section.
180 * @param SRC_POS The source position where call is being made from.
181 * Use RT_SRC_POS when possible. Optional.
182 */
183RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
184
185/**
186 * Try enter a critical section.
187 *
188 * @retval VINF_SUCCESS on success.
189 * @retval VERR_SEM_BUSY if the critsect was owned.
190 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
191 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
192 * during the operation.
193 *
194 * @param pCritSect The critical section.
195 */
196RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
197
198/**
199 * Try enter a critical section.
200 *
201 * @retval VINF_SUCCESS on success.
202 * @retval VERR_SEM_BUSY if the critsect was owned.
203 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
204 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
205 * during the operation.
206 *
207 * @param pCritSect The critical section.
208 * @param uId Where we're entering the section.
209 * @param SRC_POS The source position where call is being made from.
210 * Use RT_SRC_POS when possible. Optional.
211 */
212RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
213
214# ifdef IN_RING3 /* Crazy APIs: ring-3 only. */
215
216/**
217 * Enter multiple critical sections.
218 *
219 * This function will enter ALL the specified critical sections before returning.
220 *
221 * @returns VINF_SUCCESS on success.
222 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
223 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
224 * during the operation.
225 * @param cCritSects Number of critical sections in the array.
226 * @param papCritSects Array of critical section pointers.
227 *
228 * @remark Please note that this function will not necessarily come out favourable in a
229 * fight with other threads which are using the normal RTCritSectEnter() function.
230 * Therefore, avoid having to enter multiple critical sections!
231 */
232RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
233
234/**
235 * Enter multiple critical sections.
236 *
237 * This function will enter ALL the specified critical sections before returning.
238 *
239 * @returns VINF_SUCCESS on success.
240 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
241 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
242 * during the operation.
243 *
244 * @param cCritSects Number of critical sections in the array.
245 * @param papCritSects Array of critical section pointers.
246 * @param uId Where we're entering the section.
247 * @param SRC_POS The source position where call is being made from.
248 * Use RT_SRC_POS when possible. Optional.
249 *
250 * @remark See RTCritSectEnterMultiple().
251 */
252RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR 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 (uint32_t)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_INCLUDED_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 * Union that allows us to atomically update both the state and
385 * exclusive owner if the hardware supports cmpxchg16b or similar.
386 */
387typedef union RTCRITSECTRWSTATE
388{
389 struct
390 {
391 /** The state variable.
392 * All accesses are atomic and it bits are defined like this:
393 * Bits 0..14 - cReads.
394 * Bit 15 - Unused.
395 * Bits 16..31 - cWrites.
396 * Bit 31 - fDirection; 0=Read, 1=Write.
397 * Bits 32..46 - cWaitingReads
398 * Bit 47 - Unused.
399 * Bits 48..62 - cWaitingWrites - doesn't make sense here, not used.
400 * Bit 63 - Unused.
401 */
402 uint64_t u64State;
403 /** The write owner. */
404 RTNATIVETHREAD hNativeWriter;
405 } s;
406 RTUINT128U u128;
407} RTCRITSECTRWSTATE;
408
409
410/**
411 * Read/write critical section.
412 */
413typedef struct RTCRITSECTRW
414{
415 /** Magic used to validate the section state.
416 * RTCRITSECTRW_MAGIC is the value of an initialized & operational section. */
417 volatile uint32_t u32Magic;
418
419 /** Indicates whether hEvtRead needs resetting. */
420 bool volatile fNeedReset;
421 /** Explicit alignment padding. */
422 bool volatile afPadding[1];
423 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
424 uint16_t fFlags;
425
426 /** The number of reads made by the current writer. */
427 uint32_t volatile cWriterReads;
428 /** The number of recursions made by the current writer. (The initial grabbing
429 * of the lock counts as the first one.) */
430 uint32_t volatile cWriteRecursions;
431 /** The core state. */
432 RTCRITSECTRWSTATE volatile u;
433
434 /** What the writer threads are blocking on. */
435 RTSEMEVENT hEvtWrite;
436 /** What the read threads are blocking on when waiting for the writer to
437 * finish. */
438 RTSEMEVENTMULTI hEvtRead;
439
440 /** The validator record for the writer. */
441 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorWrite;
442 /** The validator record for the readers. */
443 R3R0PTRTYPE(PRTLOCKVALRECSHRD) pValidatorRead;
444} RTCRITSECTRW;
445AssertCompileSize(RTCRITSECTRW, HC_ARCH_BITS == 32 ? 48 : 64);
446
447/** RTCRITSECTRW::u32Magic value. (Eric Allan Dolphy, Jr.) */
448#define RTCRITSECTRW_MAGIC UINT32_C(0x19280620)
449/** RTCRITSECTRW::u32Magic dead value. */
450#define RTCRITSECTRW_MAGIC_DEAD UINT32_C(0x19640629)
451
452/** @name RTCRITSECTRW::u64State values.
453 * @note Using RTCSRW instead of RTCRITSECTRW to save space.
454 * @{ */
455#define RTCSRW_CNT_BITS 15
456#define RTCSRW_CNT_MASK UINT64_C(0x00007fff)
457
458#define RTCSRW_CNT_RD_SHIFT 0
459#define RTCSRW_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_RD_SHIFT)
460#define RTCSRW_CNT_WR_SHIFT 16
461#define RTCSRW_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_WR_SHIFT)
462
463#define RTCSRW_DIR_SHIFT 31
464#define RTCSRW_DIR_MASK RT_BIT_64(RTCSRW_DIR_SHIFT)
465#define RTCSRW_DIR_READ UINT64_C(0)
466#define RTCSRW_DIR_WRITE UINT64_C(1)
467
468#define RTCSRW_WAIT_CNT_RD_SHIFT 32
469#define RTCSRW_WAIT_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_RD_SHIFT)
470/* #define RTCSRW_WAIT_CNT_WR_SHIFT 48 */
471/* #define RTCSRW_WAIT_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_WR_SHIFT) */
472/** @} */
473
474#if defined(IN_RING3) || defined(IN_RING0)
475
476/**
477 * Initialize a critical section.
478 */
479RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
480
481/**
482 * Initialize a critical section.
483 *
484 * @returns IPRT status code.
485 * @param pThis Pointer to the read/write critical section.
486 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
487 * \#defines.
488 * @param hClass The class (no reference consumed). If NIL, no lock
489 * order validation will be performed on this lock.
490 * @param uSubClass The sub-class. This is used to define lock order
491 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
492 * recommended value here.
493 * @param pszNameFmt Name format string for the lock validator, optional
494 * (NULL). Max length is 32 bytes.
495 * @param ... Format string arguments.
496 */
497RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
498 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
499
500/**
501 * Changes the lock validator sub-class of the critical section.
502 *
503 * It is recommended to try make sure that nobody is using this critical section
504 * while changing the value.
505 *
506 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
507 * lock validator isn't compiled in or either of the parameters are
508 * invalid.
509 * @param pThis Pointer to the read/write critical section.
510 * @param uSubClass The new sub-class value.
511 */
512RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
513
514
515/**
516 * Enter a critical section with shared (read) access.
517 *
518 * @returns IPRT status code.
519 * @retval VINF_SUCCESS on success.
520 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
521 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
522 * during the operation.
523 * @param pThis Pointer to the read/write critical section.
524 */
525RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
526
527/**
528 * Enter a critical section with shared (read) access.
529 *
530 * @returns IPRT status code.
531 * @retval VINF_SUCCESS on success.
532 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
533 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
534 * during the operation.
535 *
536 * @param pThis Pointer to the read/write critical section.
537 * @param uId Where we're entering the section.
538 * @param SRC_POS The source position where call is being made from.
539 * Use RT_SRC_POS when possible. Optional.
540 */
541RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
542
543/**
544 * Try enter a critical section with shared (read) access.
545 *
546 * @returns IPRT status code.
547 * @retval VINF_SUCCESS on success.
548 * @retval VERR_SEM_BUSY if the critsect was owned.
549 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
550 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
551 * during the operation.
552 *
553 * @param pThis Pointer to the read/write critical section.
554 */
555RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
556
557/**
558 * Try enter a critical section with shared (read) access.
559 *
560 * @returns IPRT status code.
561 * @retval VINF_SUCCESS on success.
562 * @retval VERR_SEM_BUSY if the critsect was owned.
563 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
564 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
565 * during the operation.
566 *
567 * @param pThis Pointer to the read/write critical section.
568 * @param uId Where we're entering the section.
569 * @param SRC_POS The source position where call is being made from.
570 * Use RT_SRC_POS when possible. Optional.
571 */
572RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
573
574/**
575 * Leave a critical section held with shared access.
576 *
577 * @returns IPRT status code.
578 * @param pThis Pointer to the read/write critical section.
579 */
580RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
581
582
583/**
584 * Enter a critical section with exclusive (write) access.
585 *
586 * @returns IPRT status code.
587 * @retval VINF_SUCCESS on success.
588 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
589 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
590 * during the operation.
591 * @param pThis Pointer to the read/write critical section.
592 */
593RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
594
595/**
596 * Enter a critical section with exclusive (write) access.
597 *
598 * @retval VINF_SUCCESS on success.
599 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
600 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
601 * during the operation.
602 *
603 * @param pThis Pointer to the read/write critical section.
604 * @param uId Where we're entering the section.
605 * @param SRC_POS The source position where call is being made from.
606 * Use RT_SRC_POS when possible. Optional.
607 */
608RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
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 */
622RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
623
624/**
625 * Try enter a critical section with exclusive (write) access.
626 *
627 * @returns IPRT status code.
628 * @retval VINF_SUCCESS on success.
629 * @retval VERR_SEM_BUSY if the critsect was owned.
630 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
631 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
632 * during the operation.
633 *
634 * @param pThis Pointer to the read/write critical section.
635 * @param uId Where we're entering the section.
636 * @param SRC_POS The source position where call is being made from.
637 * Use RT_SRC_POS when possible. Optional.
638 */
639RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
640
641/**
642 * Leave a critical section held exclusively.
643 *
644 * @returns IPRT status code; VINF_SUCCESS, VERR_NOT_OWNER, VERR_SEM_DESTROYED,
645 * or VERR_WRONG_ORDER.
646 * @param pThis Pointer to the read/write critical section.
647 */
648RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
649
650
651/**
652 * Deletes a critical section.
653 *
654 * @returns VINF_SUCCESS.
655 * @param pThis Pointer to the read/write critical section.
656 */
657RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
658
659/**
660 * Checks the caller is the exclusive (write) owner of the critical section.
661 *
662 * @retval true if owner.
663 * @retval false if not owner.
664 * @param pThis Pointer to the read/write critical section.
665 */
666RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
667
668/**
669 * Checks if the caller is one of the read owners of the critical section.
670 *
671 * @note !CAUTION! This API doesn't work reliably if lock validation isn't
672 * enabled. Meaning, the answer is not trustworhty unless
673 * RT_LOCK_STRICT or RTCRITSECTRW_STRICT was defined at build time.
674 * Also, make sure you do not use RTCRITSECTRW_FLAGS_NO_LOCK_VAL when
675 * creating the semaphore. And finally, if you used a locking class,
676 * don't disable deadlock detection by setting cMsMinDeadlock to
677 * RT_INDEFINITE_WAIT.
678 *
679 * In short, only use this for assertions.
680 *
681 * @returns @c true if reader, @c false if not.
682 * @param pThis Pointer to the read/write critical section.
683 * @param fWannaHear What you'd like to hear when lock validation is not
684 * available. (For avoiding asserting all over the
685 * place.)
686 */
687RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
688
689/**
690 * Gets the write recursion count.
691 *
692 * @returns The write recursion count (0 if bad critsect).
693 * @param pThis Pointer to the read/write critical section.
694 */
695RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
696
697/**
698 * Gets the read recursion count of the current writer.
699 *
700 * @returns The read recursion count (0 if bad critsect).
701 * @param pThis Pointer to the read/write critical section.
702 */
703RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
704
705/**
706 * Gets the current number of reads.
707 *
708 * This includes all read recursions, so it might be higher than the number of
709 * read owners. It does not include reads done by the current writer.
710 *
711 * @returns The read count (0 if bad critsect).
712 * @param pThis Pointer to the read/write critical section.
713 */
714RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
715
716#endif /* IN_RING3 || IN_RING0 */
717
718/**
719 * Checks if a critical section is initialized or not.
720 *
721 * @retval true if initialized.
722 * @retval false if not initialized.
723 * @param pThis Pointer to the read/write critical section.
724 */
725DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
726{
727 return pThis->u32Magic == RTCRITSECTRW_MAGIC;
728}
729
730/* Lock strict build: Remap the three enter calls to the debug versions. */
731#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
732# ifdef IPRT_INCLUDED_asm_h
733# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
734# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
735# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
736# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
737# else
738# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, 0, RT_SRC_POS)
739# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, 0, RT_SRC_POS)
740# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, 0, RT_SRC_POS)
741# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, 0, RT_SRC_POS)
742# endif
743#endif
744
745/* Strict lock order: Automatically classify locks by init location. */
746#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
747# define RTCritSectRwInit(a_pThis) \
748 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
749 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
750 RTLOCKVAL_SUB_CLASS_NONE, NULL)
751#endif
752
753/** @} */
754
755RT_C_DECLS_END
756
757#endif /* !IPRT_INCLUDED_critsect_h */
758
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