VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 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
RevLine 
[1]1/** @file
[8245]2 * IPRT - Critical Sections.
[1]3 */
4
5/*
[98103]6 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[1]7 *
[96407]8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
[5999]10 *
[96407]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 *
[5999]24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
[96407]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
[5999]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.
[96407]32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[1]34 */
35
[76557]36#ifndef IPRT_INCLUDED_critsect_h
37#define IPRT_INCLUDED_critsect_h
[76507]38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
[1]41
42#include <iprt/cdefs.h>
43#include <iprt/types.h>
[25406]44#include <iprt/assert.h>
[51942]45#if defined(IN_RING3) || defined(IN_RING0)
[25406]46# include <iprt/thread.h>
[1]47#endif
[25748]48#ifdef RT_LOCK_STRICT_ORDER
49# include <iprt/lockvalidator.h>
50#endif
[1]51
[20374]52RT_C_DECLS_BEGIN
[1]53
54/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
[25167]55 *
[25168]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.
[25167]59 *
[25168]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.
[25167]66 *
67 * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
[25168]68 * and RTCritSectLeave to acquire and release access.
[25167]69 *
[25168]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 .
[25167]73 *
[1]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. */
[25368]85 volatile uint32_t u32Magic;
[1]86 /** Number of lockers.
87 * -1 if the section is free. */
[25368]88 volatile int32_t cLockers;
[1]89 /** The owner thread. */
[25368]90 volatile RTNATIVETHREAD NativeThreadOwner;
[1]91 /** Number of nested enter operations performed.
92 * Greater or equal to 1 if owned, 0 when free.
93 */
[25368]94 volatile int32_t cNestings;
[1]95 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
[25368]96 uint32_t fFlags;
97 /** The semaphore to block on. */
98 RTSEMEVENT EventSem;
99 /** Lock validator record. Only used in strict builds. */
[25607]100 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
[90398]101 /** Alignment padding. */
[25368]102 RTHCPTR Alignment;
[1]103} RTCRITSECT;
[25368]104AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
[1]105
[25368]106/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
107#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
[1]108
[25707]109/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags
110 * @{ */
[1]111/** If set, nesting(/recursion) is not allowed. */
[25368]112#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
[25685]113/** Disables lock validation. */
114#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
[33269]115/** Bootstrap hack for use with certain memory allocator locks only! */
116#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
[37419]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)
[51940]123/** Indicates that this is a ring-0 critical section. */
124#define RTCRITSECT_FLAGS_RING0 UINT32_C(0x00000010)
[25707]125/** @} */
[1]126
[45110]127
[51940]128#if defined(IN_RING3) || defined(IN_RING0)
[1]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.
[45110]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.
[1]150 */
[57004]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);
[1]153
154/**
[25704]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.
[45110]163 * @param pCritSect The critical section.
164 * @param uSubClass The new sub-class value.
[25704]165 */
166RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
167
168/**
[1]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.)
[45151]173 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
174 * during the operation.
[25685]175 * @param pCritSect The critical section.
[1]176 */
177RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
178
179/**
180 * Enter a critical section.
181 *
[45151]182 * @returns IPRT status code.
[25368]183 * @retval VINF_SUCCESS on success.
184 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]185 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
186 * during the operation.
[25368]187 *
188 * @param pCritSect The critical section.
189 * @param uId Where we're entering the section.
[57926]190 * @param SRC_POS The source position where call is being made from.
191 * Use RT_SRC_POS when possible. Optional.
[1]192 */
[25368]193RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[1]194
195/**
196 * Try enter a critical section.
197 *
[25368]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.)
[45151]201 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
202 * during the operation.
[25368]203 *
[1]204 * @param pCritSect The critical section.
205 */
206RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
207
208/**
209 * Try enter a critical section.
210 *
[25368]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.)
[45151]214 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
215 * during the operation.
[25368]216 *
217 * @param pCritSect The critical section.
218 * @param uId Where we're entering the section.
[57926]219 * @param SRC_POS The source position where call is being made from.
220 * Use RT_SRC_POS when possible. Optional.
[1]221 */
[25368]222RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[1]223
[56402]224# ifdef IN_RING3 /* Crazy APIs: ring-3 only. */
[51940]225
[1]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.)
[45151]233 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
234 * during the operation.
[1]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 */
[25368]242RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
[1]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.)
[45151]251 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
252 * during the operation.
[1]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.
[57926]257 * @param SRC_POS The source position where call is being made from.
258 * Use RT_SRC_POS when possible. Optional.
[1]259 *
260 * @remark See RTCritSectEnterMultiple().
261 */
[74373]262RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[1]263
[56402]264# endif /* IN_RING3 */
[51940]265
[1]266/**
267 * Leave a critical section.
268 *
269 * @returns VINF_SUCCESS.
[45110]270 * @param pCritSect The critical section.
[1]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 */
[25368]281RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
[1]282
283/**
284 * Deletes a critical section.
285 *
286 * @returns VINF_SUCCESS.
[45110]287 * @param pCritSect The critical section.
[1]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.
[45110]296 * @param pCritSect The critical section.
[1]297 */
298DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
299{
300 return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
301}
302
[51940]303#endif /* IN_RING3 || IN_RING0 */
[1]304
305/**
306 * Checks the section is owned by anyone.
307 *
308 * @returns true if owned.
309 * @returns false if not owned.
[45110]310 * @param pCritSect The critical section.
[1]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.
[45110]322 * @param pCritSect The critical section.
[1]323 */
324DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
325{
326 return pCritSect->NativeThreadOwner;
327}
328
[20008]329/**
330 * Checks if a critical section is initialized or not.
331 *
332 * @returns true if initialized.
333 * @returns false if not initialized.
[45110]334 * @param pCritSect The critical section.
[20008]335 */
336DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
337{
338 return pCritSect->u32Magic == RTCRITSECT_MAGIC;
339}
[1]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{
[85226]349 return (uint32_t)pCritSect->cNestings;
[1]350}
351
[19531]352/**
353 * Gets the waiter count
354 *
355 * @returns The waiter count
356 * @param pCritSect The Critical section
357 */
[19568]358DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
[19531]359{
360 return pCritSect->cLockers;
361}
362
[25748]363/* Lock strict build: Remap the three enter calls to the debug versions. */
[36492]364#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
[76557]365# ifdef IPRT_INCLUDED_asm_h
[25368]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
[25748]376/* Strict lock order: Automatically classify locks by init location. */
[45110]377#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
[25748]378# define RTCritSectInit(pCritSect) \
379 RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
380 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
381 RTLOCKVAL_SUB_CLASS_NONE, NULL)
382#endif
383
[45110]384/** @} */
385
386
387
388/** @defgroup grp_rt_critsectrw RTCritSectRw - Read/Write Critical Sections
389 * @ingroup grp_rt
390 * @{
391 */
392
393/**
[90649]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/**
[45110]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;
[90649]441 /** The core state. */
442 RTCRITSECTRWSTATE volatile u;
[45110]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
[45151]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)
[45110]467
[45151]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
[51940]484#if defined(IN_RING3) || defined(IN_RING0)
[45110]485
486/**
487 * Initialize a critical section.
488 */
[45151]489RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
[45110]490
491/**
492 * Initialize a critical section.
493 *
[45151]494 * @returns IPRT status code.
495 * @param pThis Pointer to the read/write critical section.
[45110]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 */
[57004]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);
[45110]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.
[45151]519 * @param pThis Pointer to the read/write critical section.
[45110]520 * @param uSubClass The new sub-class value.
521 */
[45151]522RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
[45110]523
524
525/**
526 * Enter a critical section with shared (read) access.
527 *
[45151]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.
[45110]534 */
[45151]535RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
[45110]536
537/**
538 * Enter a critical section with shared (read) access.
539 *
[45151]540 * @returns IPRT status code.
[45110]541 * @retval VINF_SUCCESS on success.
542 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]543 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
544 * during the operation.
[45110]545 *
[45151]546 * @param pThis Pointer to the read/write critical section.
[45110]547 * @param uId Where we're entering the section.
[57926]548 * @param SRC_POS The source position where call is being made from.
549 * Use RT_SRC_POS when possible. Optional.
[45110]550 */
[45151]551RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]552
553/**
554 * Try enter a critical section with shared (read) access.
555 *
[45151]556 * @returns IPRT status code.
[45110]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.)
[45151]560 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
561 * during the operation.
[45110]562 *
[45151]563 * @param pThis Pointer to the read/write critical section.
[45110]564 */
[45151]565RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
[45110]566
567/**
568 * Try enter a critical section with shared (read) access.
569 *
[45151]570 * @returns IPRT status code.
[45110]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.)
[45151]574 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
575 * during the operation.
[45110]576 *
[45151]577 * @param pThis Pointer to the read/write critical section.
[45110]578 * @param uId Where we're entering the section.
[57926]579 * @param SRC_POS The source position where call is being made from.
580 * Use RT_SRC_POS when possible. Optional.
[45110]581 */
[45151]582RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]583
584/**
585 * Leave a critical section held with shared access.
586 *
[45151]587 * @returns IPRT status code.
588 * @param pThis Pointer to the read/write critical section.
[45110]589 */
[45151]590RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
[45110]591
592
593/**
594 * Enter a critical section with exclusive (write) access.
595 *
[45151]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.
[45110]602 */
[45151]603RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
[45110]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.)
[45151]610 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
611 * during the operation.
[45110]612 *
[45151]613 * @param pThis Pointer to the read/write critical section.
[45110]614 * @param uId Where we're entering the section.
[57926]615 * @param SRC_POS The source position where call is being made from.
616 * Use RT_SRC_POS when possible. Optional.
[45110]617 */
[45151]618RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]619
620/**
621 * Try enter a critical section with exclusive (write) access.
622 *
[45151]623 * @returns IPRT status code.
[45110]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.)
[45151]627 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
628 * during the operation.
[45110]629 *
[45151]630 * @param pThis Pointer to the read/write critical section.
[45110]631 */
[45151]632RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
[45110]633
634/**
635 * Try enter a critical section with exclusive (write) access.
636 *
[45151]637 * @returns IPRT status code.
[45110]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.)
[45151]641 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
642 * during the operation.
[45110]643 *
[45151]644 * @param pThis Pointer to the read/write critical section.
[45110]645 * @param uId Where we're entering the section.
[57926]646 * @param SRC_POS The source position where call is being made from.
647 * Use RT_SRC_POS when possible. Optional.
[45110]648 */
[45151]649RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]650
651/**
652 * Leave a critical section held exclusively.
653 *
[45151]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.
[45110]657 */
[45151]658RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
[45110]659
660
661/**
662 * Deletes a critical section.
663 *
664 * @returns VINF_SUCCESS.
[45151]665 * @param pThis Pointer to the read/write critical section.
[45110]666 */
[45151]667RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
[45110]668
669/**
670 * Checks the caller is the exclusive (write) owner of the critical section.
671 *
[57978]672 * @retval true if owner.
673 * @retval false if not owner.
[45151]674 * @param pThis Pointer to the read/write critical section.
[45110]675 */
[45151]676RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
[45110]677
678/**
[45151]679 * Checks if the caller is one of the read owners of the critical section.
[45110]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 *
[45151]691 * @returns @c true if reader, @c false if not.
692 * @param pThis Pointer to the read/write critical section.
[45110]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 */
[45151]697RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
[45110]698
699/**
700 * Gets the write recursion count.
701 *
702 * @returns The write recursion count (0 if bad critsect).
[45151]703 * @param pThis Pointer to the read/write critical section.
[45110]704 */
[45151]705RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
[45110]706
707/**
708 * Gets the read recursion count of the current writer.
709 *
710 * @returns The read recursion count (0 if bad critsect).
[45151]711 * @param pThis Pointer to the read/write critical section.
[45110]712 */
[45151]713RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
[45110]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).
[45151]722 * @param pThis Pointer to the read/write critical section.
[45110]723 */
[45151]724RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
[45110]725
[51940]726#endif /* IN_RING3 || IN_RING0 */
[45110]727
728/**
729 * Checks if a critical section is initialized or not.
730 *
[57978]731 * @retval true if initialized.
732 * @retval false if not initialized.
[45151]733 * @param pThis Pointer to the read/write critical section.
[45110]734 */
[45151]735DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
[45110]736{
[45151]737 return pThis->u32Magic == RTCRITSECTRW_MAGIC;
[45110]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)
[76557]742# ifdef IPRT_INCLUDED_asm_h
[45151]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)
[45110]747# else
[45151]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)
[45110]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)
[45151]757# define RTCritSectRwInit(a_pThis) \
758 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
[45110]759 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
760 RTLOCKVAL_SUB_CLASS_NONE, NULL)
761#endif
762
[1]763/** @} */
764
[20374]765RT_C_DECLS_END
[1]766
[76585]767#endif /* !IPRT_INCLUDED_critsect_h */
[1]768
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use