VirtualBox

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

Last change on this file since 106061 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.4 KB
Line 
1/** @file
2 * IPRT - Critical Sections.
3 */
4
5/*
6 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef IPRT_INCLUDED_critsect_h
37#define IPRT_INCLUDED_critsect_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/cdefs.h>
43#include <iprt/types.h>
44#include <iprt/assert.h>
45#if defined(IN_RING3) || defined(IN_RING0)
46# include <iprt/thread.h>
47#endif
48#ifdef RT_LOCK_STRICT_ORDER
49# include <iprt/lockvalidator.h>
50#endif
51
52RT_C_DECLS_BEGIN
53
54/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
55 *
56 * "Critical section" synchronization primitives can be used to
57 * protect a section of code or data to which access must be exclusive;
58 * only one thread can hold access to a critical section at one time.
59 *
60 * A critical section is a fast recursive write lock; if the critical
61 * section is not acquired, then entering it is fast (requires no system
62 * call). IPRT uses the Windows terminology here; on other platform, this
63 * might be called a "futex" or a "fast mutex". As opposed to IPRT
64 * "fast mutexes" (see @ref grp_rt_sems_fast_mutex ), critical sections
65 * are recursive.
66 *
67 * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
68 * and RTCritSectLeave to acquire and release access.
69 *
70 * For an overview of all types of synchronization primitives provided
71 * by IPRT (event, mutex/fast mutex/read-write mutex semaphores), see
72 * @ref grp_rt_sems .
73 *
74 * @ingroup grp_rt
75 * @{
76 */
77
78/**
79 * Critical section.
80 */
81typedef struct RTCRITSECT
82{
83 /** Magic used to validate the section state.
84 * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
85 volatile uint32_t u32Magic;
86 /** Number of lockers.
87 * -1 if the section is free. */
88 volatile int32_t cLockers;
89 /** The owner thread. */
90 volatile RTNATIVETHREAD NativeThreadOwner;
91 /** Number of nested enter operations performed.
92 * Greater or equal to 1 if owned, 0 when free.
93 */
94 volatile int32_t cNestings;
95 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
96 uint32_t fFlags;
97 /** The semaphore to block on. */
98 RTSEMEVENT EventSem;
99 /** Lock validator record. Only used in strict builds. */
100 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
101 /** Alignment padding. */
102 RTHCPTR Alignment;
103} RTCRITSECT;
104AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
105
106/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
107#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
108
109/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags
110 * @{ */
111/** If set, nesting(/recursion) is not allowed. */
112#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
113/** Disables lock validation. */
114#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
115/** Bootstrap hack for use with certain memory allocator locks only! */
116#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
117/** If set, the critical section becomes a dummy that doesn't serialize any
118 * threads. This flag can only be set at creation time.
119 *
120 * The intended use is avoiding lots of conditional code where some component
121 * might or might not require entering a critical section before access. */
122#define RTCRITSECT_FLAGS_NOP UINT32_C(0x00000008)
123/** Indicates that this is a ring-0 critical section. */
124#define RTCRITSECT_FLAGS_RING0 UINT32_C(0x00000010)
125/** @} */
126
127
128#if defined(IN_RING3) || defined(IN_RING0)
129
130/**
131 * Initialize a critical section.
132 */
133RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
134
135/**
136 * Initialize a critical section with a simple name,
137 */
138RTDECL(int) RTCritSectInitNamed(PRTCRITSECT pCritSect, const char *pszName);
139
140/**
141 * Initialize a critical section.
142 *
143 * @returns iprt status code.
144 * @param pCritSect Pointer to the critical section structure.
145 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
146 * \#defines.
147 * @param hClass The class (no reference consumed). If NIL, no lock
148 * order validation will be performed on this lock.
149 * @param uSubClass The sub-class. This is used to define lock order
150 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
151 * recommended value here.
152 * @param pszNameFmt Name format string for the lock validator, optional
153 * (NULL). Max length is 32 bytes.
154 * @param ... Format string arguments.
155 */
156RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
157 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
158
159/**
160 * Changes the lock validator sub-class of the critical section.
161 *
162 * It is recommended to try make sure that nobody is using this critical section
163 * while changing the value.
164 *
165 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
166 * lock validator isn't compiled in or either of the parameters are
167 * invalid.
168 * @param pCritSect The critical section.
169 * @param uSubClass The new sub-class value.
170 */
171RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
172
173/**
174 * Enter a critical section.
175 *
176 * @returns VINF_SUCCESS on success.
177 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
178 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
179 * during the operation.
180 * @param pCritSect The critical section.
181 */
182RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
183
184/**
185 * Enter a critical section.
186 *
187 * @returns IPRT status code.
188 * @retval VINF_SUCCESS on success.
189 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
190 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
191 * during the operation.
192 *
193 * @param pCritSect The critical section.
194 * @param uId Where we're entering the section.
195 * @param SRC_POS The source position where call is being made from.
196 * Use RT_SRC_POS when possible. Optional.
197 */
198RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
199
200/**
201 * Try enter a critical section.
202 *
203 * @retval VINF_SUCCESS on success.
204 * @retval VERR_SEM_BUSY if the critsect was owned.
205 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
206 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
207 * during the operation.
208 *
209 * @param pCritSect The critical section.
210 */
211RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
212
213/**
214 * Try enter a critical section.
215 *
216 * @retval VINF_SUCCESS on success.
217 * @retval VERR_SEM_BUSY if the critsect was owned.
218 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
219 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
220 * during the operation.
221 *
222 * @param pCritSect The critical section.
223 * @param uId Where we're entering the section.
224 * @param SRC_POS The source position where call is being made from.
225 * Use RT_SRC_POS when possible. Optional.
226 */
227RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
228
229# ifdef IN_RING3 /* Crazy APIs: ring-3 only. */
230
231/**
232 * Enter multiple critical sections.
233 *
234 * This function will enter ALL the specified critical sections before returning.
235 *
236 * @returns VINF_SUCCESS on success.
237 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
238 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
239 * during the operation.
240 * @param cCritSects Number of critical sections in the array.
241 * @param papCritSects Array of critical section pointers.
242 *
243 * @remark Please note that this function will not necessarily come out favourable in a
244 * fight with other threads which are using the normal RTCritSectEnter() function.
245 * Therefore, avoid having to enter multiple critical sections!
246 */
247RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
248
249/**
250 * Enter multiple critical sections.
251 *
252 * This function will enter ALL the specified critical sections before returning.
253 *
254 * @returns VINF_SUCCESS on success.
255 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
256 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
257 * during the operation.
258 *
259 * @param cCritSects Number of critical sections in the array.
260 * @param papCritSects Array of critical section pointers.
261 * @param uId Where we're entering the section.
262 * @param SRC_POS The source position where call is being made from.
263 * Use RT_SRC_POS when possible. Optional.
264 *
265 * @remark See RTCritSectEnterMultiple().
266 */
267RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL);
268
269# endif /* IN_RING3 */
270
271/**
272 * Leave a critical section.
273 *
274 * @returns VINF_SUCCESS.
275 * @param pCritSect The critical section.
276 */
277RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);
278
279/**
280 * Leave multiple critical sections.
281 *
282 * @returns VINF_SUCCESS.
283 * @param cCritSects Number of critical sections in the array.
284 * @param papCritSects Array of critical section pointers.
285 */
286RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
287
288/**
289 * Deletes a critical section.
290 *
291 * @returns VINF_SUCCESS.
292 * @param pCritSect The critical section.
293 */
294RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);
295
296/**
297 * Checks the caller is the owner of the critical section.
298 *
299 * @returns true if owner.
300 * @returns false if not owner.
301 * @param pCritSect The critical section.
302 */
303DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
304{
305 return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
306}
307
308#endif /* IN_RING3 || IN_RING0 */
309
310/**
311 * Checks the section is owned by anyone.
312 *
313 * @returns true if owned.
314 * @returns false if not owned.
315 * @param pCritSect The critical section.
316 */
317DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
318{
319 return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
320}
321
322/**
323 * Gets the thread id of the critical section owner.
324 *
325 * @returns Thread id of the owner thread if owned.
326 * @returns NIL_RTNATIVETHREAD is not owned.
327 * @param pCritSect The critical section.
328 */
329DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
330{
331 return pCritSect->NativeThreadOwner;
332}
333
334/**
335 * Checks if a critical section is initialized or not.
336 *
337 * @returns true if initialized.
338 * @returns false if not initialized.
339 * @param pCritSect The critical section.
340 */
341DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
342{
343 return pCritSect->u32Magic == RTCRITSECT_MAGIC;
344}
345
346/**
347 * Gets the recursion depth.
348 *
349 * @returns The recursion depth.
350 * @param pCritSect The Critical section
351 */
352DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
353{
354 return (uint32_t)pCritSect->cNestings;
355}
356
357/**
358 * Gets the waiter count
359 *
360 * @returns The waiter count
361 * @param pCritSect The Critical section
362 */
363DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
364{
365 return pCritSect->cLockers;
366}
367
368/* Lock strict build: Remap the three enter calls to the debug versions. */
369#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
370# ifdef IPRT_INCLUDED_asm_h
371# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
372# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
373# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
374# else
375# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS)
376# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS)
377# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 0, RT_SRC_POS)
378# endif
379#endif
380
381/* Strict lock order: Automatically classify locks by init location. */
382#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
383# undef RTCritSectInit
384# define RTCritSectInit(pCritSect) \
385 RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
386 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
387 RTLOCKVAL_SUB_CLASS_NONE, NULL)
388
389# undef RTCritSectInitNamed
390# define RTCritSectInitNamed(a_pCritSect, a_pszName) \
391 RTCritSectInitEx((a_pCritSect), 0 /*fFlags*/, \
392 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
393 RTLOCKVAL_SUB_CLASS_NONE, "%s", a_pszName)
394#endif
395
396/** @} */
397
398
399
400/** @defgroup grp_rt_critsectrw RTCritSectRw - Read/Write Critical Sections
401 * @ingroup grp_rt
402 * @{
403 */
404
405/**
406 * Union that allows us to atomically update both the state and
407 * exclusive owner if the hardware supports cmpxchg16b or similar.
408 */
409typedef union RTCRITSECTRWSTATE
410{
411 struct
412 {
413 /** The state variable.
414 * All accesses are atomic and it bits are defined like this:
415 * Bits 0..14 - cReads.
416 * Bit 15 - Unused.
417 * Bits 16..31 - cWrites.
418 * Bit 31 - fDirection; 0=Read, 1=Write.
419 * Bits 32..46 - cWaitingReads
420 * Bit 47 - Unused.
421 * Bits 48..62 - cWaitingWrites - doesn't make sense here, not used.
422 * Bit 63 - Unused.
423 */
424 uint64_t u64State;
425 /** The write owner. */
426 RTNATIVETHREAD hNativeWriter;
427 } s;
428 RTUINT128U u128;
429} RTCRITSECTRWSTATE;
430
431
432/**
433 * Read/write critical section.
434 */
435typedef struct RTCRITSECTRW
436{
437 /** Magic used to validate the section state.
438 * RTCRITSECTRW_MAGIC is the value of an initialized & operational section. */
439 volatile uint32_t u32Magic;
440
441 /** Indicates whether hEvtRead needs resetting. */
442 bool volatile fNeedReset;
443 /** Explicit alignment padding. */
444 bool volatile afPadding[1];
445 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
446 uint16_t fFlags;
447
448 /** The number of reads made by the current writer. */
449 uint32_t volatile cWriterReads;
450 /** The number of recursions made by the current writer. (The initial grabbing
451 * of the lock counts as the first one.) */
452 uint32_t volatile cWriteRecursions;
453 /** The core state. */
454 RTCRITSECTRWSTATE volatile u;
455
456 /** What the writer threads are blocking on. */
457 RTSEMEVENT hEvtWrite;
458 /** What the read threads are blocking on when waiting for the writer to
459 * finish. */
460 RTSEMEVENTMULTI hEvtRead;
461
462 /** The validator record for the writer. */
463 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorWrite;
464 /** The validator record for the readers. */
465 R3R0PTRTYPE(PRTLOCKVALRECSHRD) pValidatorRead;
466} RTCRITSECTRW;
467AssertCompileSize(RTCRITSECTRW, HC_ARCH_BITS == 32 ? 48 : 64);
468
469/** RTCRITSECTRW::u32Magic value. (Eric Allan Dolphy, Jr.) */
470#define RTCRITSECTRW_MAGIC UINT32_C(0x19280620)
471/** RTCRITSECTRW::u32Magic dead value. */
472#define RTCRITSECTRW_MAGIC_DEAD UINT32_C(0x19640629)
473
474/** @name RTCRITSECTRW::u64State values.
475 * @note Using RTCSRW instead of RTCRITSECTRW to save space.
476 * @{ */
477#define RTCSRW_CNT_BITS 15
478#define RTCSRW_CNT_MASK UINT64_C(0x00007fff)
479
480#define RTCSRW_CNT_RD_SHIFT 0
481#define RTCSRW_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_RD_SHIFT)
482#define RTCSRW_CNT_WR_SHIFT 16
483#define RTCSRW_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_WR_SHIFT)
484
485#define RTCSRW_DIR_SHIFT 31
486#define RTCSRW_DIR_MASK RT_BIT_64(RTCSRW_DIR_SHIFT)
487#define RTCSRW_DIR_READ UINT64_C(0)
488#define RTCSRW_DIR_WRITE UINT64_C(1)
489
490#define RTCSRW_WAIT_CNT_RD_SHIFT 32
491#define RTCSRW_WAIT_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_RD_SHIFT)
492/* #define RTCSRW_WAIT_CNT_WR_SHIFT 48 */
493/* #define RTCSRW_WAIT_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_WR_SHIFT) */
494/** @} */
495
496#if defined(IN_RING3) || defined(IN_RING0)
497
498/**
499 * Initialize a read/write critical section.
500 */
501RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
502
503/**
504 * Initialize a read/write critical section with a simple name.
505 */
506RTDECL(int) RTCritSectRwInitNamed(PRTCRITSECTRW pThis, const char *pszName);
507
508/**
509 * Initialize a read/write critical section.
510 *
511 * @returns IPRT status code.
512 * @param pThis Pointer to the read/write critical section.
513 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
514 * \#defines.
515 * @param hClass The class (no reference consumed). If NIL, no lock
516 * order validation will be performed on this lock.
517 * @param uSubClass The sub-class. This is used to define lock order
518 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
519 * recommended value here.
520 * @param pszNameFmt Name format string for the lock validator, optional
521 * (NULL). Max length is 32 bytes.
522 * @param ... Format string arguments.
523 */
524RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
525 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
526
527/**
528 * Changes the lock validator sub-class of the critical section.
529 *
530 * It is recommended to try make sure that nobody is using this critical section
531 * while changing the value.
532 *
533 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
534 * lock validator isn't compiled in or either of the parameters are
535 * invalid.
536 * @param pThis Pointer to the read/write critical section.
537 * @param uSubClass The new sub-class value.
538 */
539RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
540
541
542/**
543 * Enter a critical section with shared (read) access.
544 *
545 * @returns IPRT status code.
546 * @retval VINF_SUCCESS on success.
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 * @param pThis Pointer to the read/write critical section.
551 */
552RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
553
554/**
555 * Enter a critical section with shared (read) access.
556 *
557 * @returns IPRT status code.
558 * @retval VINF_SUCCESS on success.
559 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
560 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
561 * during the operation.
562 *
563 * @param pThis Pointer to the read/write critical section.
564 * @param uId Where we're entering the section.
565 * @param SRC_POS The source position where call is being made from.
566 * Use RT_SRC_POS when possible. Optional.
567 */
568RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
569
570/**
571 * Try enter a critical section with shared (read) access.
572 *
573 * @returns IPRT status code.
574 * @retval VINF_SUCCESS on success.
575 * @retval VERR_SEM_BUSY if the critsect was owned.
576 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
577 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
578 * during the operation.
579 *
580 * @param pThis Pointer to the read/write critical section.
581 */
582RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
583
584/**
585 * Try enter a critical section with shared (read) access.
586 *
587 * @returns IPRT status code.
588 * @retval VINF_SUCCESS on success.
589 * @retval VERR_SEM_BUSY if the critsect was owned.
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 SRC_POS The source position where call is being made from.
597 * Use RT_SRC_POS when possible. Optional.
598 */
599RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
600
601/**
602 * Leave a critical section held with shared access.
603 *
604 * @returns IPRT status code.
605 * @param pThis Pointer to the read/write critical section.
606 */
607RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
608
609
610/**
611 * Enter a critical section with exclusive (write) access.
612 *
613 * @returns IPRT status code.
614 * @retval VINF_SUCCESS on success.
615 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
616 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
617 * during the operation.
618 * @param pThis Pointer to the read/write critical section.
619 */
620RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
621
622/**
623 * Enter a critical section with exclusive (write) access.
624 *
625 * @retval VINF_SUCCESS on success.
626 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
627 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
628 * during the operation.
629 *
630 * @param pThis Pointer to the read/write critical section.
631 * @param uId Where we're entering the section.
632 * @param SRC_POS The source position where call is being made from.
633 * Use RT_SRC_POS when possible. Optional.
634 */
635RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
636
637/**
638 * Try enter a critical section with exclusive (write) access.
639 *
640 * @returns IPRT status code.
641 * @retval VINF_SUCCESS on success.
642 * @retval VERR_SEM_BUSY if the critsect was owned.
643 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
644 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
645 * during the operation.
646 *
647 * @param pThis Pointer to the read/write critical section.
648 */
649RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
650
651/**
652 * Try enter a critical section with exclusive (write) access.
653 *
654 * @returns IPRT status code.
655 * @retval VINF_SUCCESS on success.
656 * @retval VERR_SEM_BUSY if the critsect was owned.
657 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
658 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
659 * during the operation.
660 *
661 * @param pThis Pointer to the read/write critical section.
662 * @param uId Where we're entering the section.
663 * @param SRC_POS The source position where call is being made from.
664 * Use RT_SRC_POS when possible. Optional.
665 */
666RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
667
668/**
669 * Leave a critical section held exclusively.
670 *
671 * @returns IPRT status code; VINF_SUCCESS, VERR_NOT_OWNER, VERR_SEM_DESTROYED,
672 * or VERR_WRONG_ORDER.
673 * @param pThis Pointer to the read/write critical section.
674 */
675RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
676
677
678/**
679 * Deletes a critical section.
680 *
681 * @returns VINF_SUCCESS.
682 * @param pThis Pointer to the read/write critical section.
683 */
684RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
685
686/**
687 * Checks the caller is the exclusive (write) owner of the critical section.
688 *
689 * @retval true if owner.
690 * @retval false if not owner.
691 * @param pThis Pointer to the read/write critical section.
692 */
693RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
694
695/**
696 * Checks if the caller is one of the read owners of the critical section.
697 *
698 * @note !CAUTION! This API doesn't work reliably if lock validation isn't
699 * enabled. Meaning, the answer is not trustworhty unless
700 * RT_LOCK_STRICT or RTCRITSECTRW_STRICT was defined at build time.
701 * Also, make sure you do not use RTCRITSECTRW_FLAGS_NO_LOCK_VAL when
702 * creating the semaphore. And finally, if you used a locking class,
703 * don't disable deadlock detection by setting cMsMinDeadlock to
704 * RT_INDEFINITE_WAIT.
705 *
706 * In short, only use this for assertions.
707 *
708 * @returns @c true if reader, @c false if not.
709 * @param pThis Pointer to the read/write critical section.
710 * @param fWannaHear What you'd like to hear when lock validation is not
711 * available. (For avoiding asserting all over the
712 * place.)
713 */
714RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
715
716/**
717 * Gets the write recursion count.
718 *
719 * @returns The write recursion count (0 if bad critsect).
720 * @param pThis Pointer to the read/write critical section.
721 */
722RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
723
724/**
725 * Gets the read recursion count of the current writer.
726 *
727 * @returns The read recursion count (0 if bad critsect).
728 * @param pThis Pointer to the read/write critical section.
729 */
730RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
731
732/**
733 * Gets the current number of reads.
734 *
735 * This includes all read recursions, so it might be higher than the number of
736 * read owners. It does not include reads done by the current writer.
737 *
738 * @returns The read count (0 if bad critsect).
739 * @param pThis Pointer to the read/write critical section.
740 */
741RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
742
743#endif /* IN_RING3 || IN_RING0 */
744
745/**
746 * Checks if a critical section is initialized or not.
747 *
748 * @retval true if initialized.
749 * @retval false if not initialized.
750 * @param pThis Pointer to the read/write critical section.
751 */
752DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
753{
754 return pThis->u32Magic == RTCRITSECTRW_MAGIC;
755}
756
757/* Lock strict build: Remap the three enter calls to the debug versions. */
758#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
759# ifdef IPRT_INCLUDED_asm_h
760# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
761# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
762# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
763# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
764# else
765# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, 0, RT_SRC_POS)
766# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, 0, RT_SRC_POS)
767# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, 0, RT_SRC_POS)
768# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, 0, RT_SRC_POS)
769# endif
770#endif
771
772/* Strict lock order: Automatically classify locks by init location. */
773#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
774# define RTCritSectRwInit(a_pThis) \
775 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
776 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
777 RTLOCKVAL_SUB_CLASS_NONE, NULL)
778
779# define RTCritSectRwInitNamed(a_pThis, a_pszName) \
780 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
781 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
782 RTLOCKVAL_SUB_CLASS_NONE, "%s", a_pszName)
783#endif
784
785/** @} */
786
787RT_C_DECLS_END
788
789#endif /* !IPRT_INCLUDED_critsect_h */
790
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