VirtualBox

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

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

© 2023 Oracle
ContactPrivacy policyTerms of Use