VirtualBox

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

Last change on this file since 77807 was 76585, checked in by vboxsync, 6 years ago

*: scm --fix-header-guard-endif

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.0 KB
RevLine 
[1]1/** @file
[8245]2 * IPRT - Critical Sections.
[1]3 */
4
5/*
[76553]6 * Copyright (C) 2006-2019 Oracle Corporation
[1]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
[5999]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.
[1]24 */
25
[76557]26#ifndef IPRT_INCLUDED_critsect_h
27#define IPRT_INCLUDED_critsect_h
[76507]28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
[1]31
32#include <iprt/cdefs.h>
33#include <iprt/types.h>
[25406]34#include <iprt/assert.h>
[51942]35#if defined(IN_RING3) || defined(IN_RING0)
[25406]36# include <iprt/thread.h>
[1]37#endif
[25748]38#ifdef RT_LOCK_STRICT_ORDER
39# include <iprt/lockvalidator.h>
40#endif
[1]41
[20374]42RT_C_DECLS_BEGIN
[1]43
44/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
[25167]45 *
[25168]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.
[25167]49 *
[25168]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.
[25167]56 *
57 * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
[25168]58 * and RTCritSectLeave to acquire and release access.
[25167]59 *
[25168]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 .
[25167]63 *
[1]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. */
[25368]75 volatile uint32_t u32Magic;
[1]76 /** Number of lockers.
77 * -1 if the section is free. */
[25368]78 volatile int32_t cLockers;
[1]79 /** The owner thread. */
[25368]80 volatile RTNATIVETHREAD NativeThreadOwner;
[1]81 /** Number of nested enter operations performed.
82 * Greater or equal to 1 if owned, 0 when free.
83 */
[25368]84 volatile int32_t cNestings;
[1]85 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
[25368]86 uint32_t fFlags;
87 /** The semaphore to block on. */
88 RTSEMEVENT EventSem;
89 /** Lock validator record. Only used in strict builds. */
[25607]90 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
[25368]91 /** Alignmnet padding. */
92 RTHCPTR Alignment;
[1]93} RTCRITSECT;
[25368]94AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
[1]95
[25368]96/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
97#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
[1]98
[25707]99/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags
100 * @{ */
[1]101/** If set, nesting(/recursion) is not allowed. */
[25368]102#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
[25685]103/** Disables lock validation. */
104#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
[33269]105/** Bootstrap hack for use with certain memory allocator locks only! */
106#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
[37419]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)
[51940]113/** Indicates that this is a ring-0 critical section. */
114#define RTCRITSECT_FLAGS_RING0 UINT32_C(0x00000010)
[25707]115/** @} */
[1]116
[45110]117
[51940]118#if defined(IN_RING3) || defined(IN_RING0)
[1]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.
[45110]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.
[1]140 */
[57004]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);
[1]143
144/**
[25704]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.
[45110]153 * @param pCritSect The critical section.
154 * @param uSubClass The new sub-class value.
[25704]155 */
156RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
157
158/**
[1]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.)
[45151]163 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
164 * during the operation.
[25685]165 * @param pCritSect The critical section.
[1]166 */
167RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
168
169/**
170 * Enter a critical section.
171 *
[45151]172 * @returns IPRT status code.
[25368]173 * @retval VINF_SUCCESS on success.
174 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]175 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
176 * during the operation.
[25368]177 *
178 * @param pCritSect The critical section.
179 * @param uId Where we're entering the section.
[57926]180 * @param SRC_POS The source position where call is being made from.
181 * Use RT_SRC_POS when possible. Optional.
[1]182 */
[25368]183RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[1]184
185/**
186 * Try enter a critical section.
187 *
[25368]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.)
[45151]191 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
192 * during the operation.
[25368]193 *
[1]194 * @param pCritSect The critical section.
195 */
196RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
197
198/**
199 * Try enter a critical section.
200 *
[25368]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.)
[45151]204 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
205 * during the operation.
[25368]206 *
207 * @param pCritSect The critical section.
208 * @param uId Where we're entering the section.
[57926]209 * @param SRC_POS The source position where call is being made from.
210 * Use RT_SRC_POS when possible. Optional.
[1]211 */
[25368]212RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[1]213
[56402]214# ifdef IN_RING3 /* Crazy APIs: ring-3 only. */
[51940]215
[1]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.)
[45151]223 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
224 * during the operation.
[1]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 */
[25368]232RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
[1]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.)
[45151]241 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
242 * during the operation.
[1]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.
[57926]247 * @param SRC_POS The source position where call is being made from.
248 * Use RT_SRC_POS when possible. Optional.
[1]249 *
250 * @remark See RTCritSectEnterMultiple().
251 */
[74373]252RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[1]253
[56402]254# endif /* IN_RING3 */
[51940]255
[1]256/**
257 * Leave a critical section.
258 *
259 * @returns VINF_SUCCESS.
[45110]260 * @param pCritSect The critical section.
[1]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 */
[25368]271RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
[1]272
273/**
274 * Deletes a critical section.
275 *
276 * @returns VINF_SUCCESS.
[45110]277 * @param pCritSect The critical section.
[1]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.
[45110]286 * @param pCritSect The critical section.
[1]287 */
288DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
289{
290 return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
291}
292
[51940]293#endif /* IN_RING3 || IN_RING0 */
[1]294
295/**
296 * Checks the section is owned by anyone.
297 *
298 * @returns true if owned.
299 * @returns false if not owned.
[45110]300 * @param pCritSect The critical section.
[1]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.
[45110]312 * @param pCritSect The critical section.
[1]313 */
314DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
315{
316 return pCritSect->NativeThreadOwner;
317}
318
[20008]319/**
320 * Checks if a critical section is initialized or not.
321 *
322 * @returns true if initialized.
323 * @returns false if not initialized.
[45110]324 * @param pCritSect The critical section.
[20008]325 */
326DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
327{
328 return pCritSect->u32Magic == RTCRITSECT_MAGIC;
329}
[1]330
331/**
332 * Gets the recursion depth.
333 *
334 * @returns The recursion depth.
335 * @param pCritSect The Critical section
336 */
337DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
338{
339 return pCritSect->cNestings;
340}
341
[19531]342/**
343 * Gets the waiter count
344 *
345 * @returns The waiter count
346 * @param pCritSect The Critical section
347 */
[19568]348DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
[19531]349{
350 return pCritSect->cLockers;
351}
352
[25748]353/* Lock strict build: Remap the three enter calls to the debug versions. */
[36492]354#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
[76557]355# ifdef IPRT_INCLUDED_asm_h
[25368]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
[25748]366/* Strict lock order: Automatically classify locks by init location. */
[45110]367#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
[25748]368# define RTCritSectInit(pCritSect) \
369 RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
370 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
371 RTLOCKVAL_SUB_CLASS_NONE, NULL)
372#endif
373
[45110]374/** @} */
375
376
377
378/** @defgroup grp_rt_critsectrw RTCritSectRw - Read/Write Critical Sections
379 * @ingroup grp_rt
380 * @{
381 */
382
383/**
384 * Read/write critical section.
385 */
386typedef struct RTCRITSECTRW
387{
388 /** Magic used to validate the section state.
389 * RTCRITSECTRW_MAGIC is the value of an initialized & operational section. */
390 volatile uint32_t u32Magic;
391
392 /** Indicates whether hEvtRead needs resetting. */
393 bool volatile fNeedReset;
394 /** Explicit alignment padding. */
395 bool volatile afPadding[1];
396 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
397 uint16_t fFlags;
398
399 /** The state variable.
400 * All accesses are atomic and it bits are defined like this:
401 * Bits 0..14 - cReads.
402 * Bit 15 - Unused.
403 * Bits 16..31 - cWrites. - doesn't make sense here
404 * Bit 31 - fDirection; 0=Read, 1=Write.
405 * Bits 32..46 - cWaitingReads
406 * Bit 47 - Unused.
407 * Bits 48..62 - cWaitingWrites
408 * Bit 63 - Unused.
409 */
410 uint64_t volatile u64State;
411 /** The write owner. */
412 RTNATIVETHREAD volatile hNativeWriter;
413 /** The number of reads made by the current writer. */
414 uint32_t volatile cWriterReads;
415 /** The number of recursions made by the current writer. (The initial grabbing
416 * of the lock counts as the first one.) */
417 uint32_t volatile cWriteRecursions;
418
419 /** What the writer threads are blocking on. */
420 RTSEMEVENT hEvtWrite;
421 /** What the read threads are blocking on when waiting for the writer to
422 * finish. */
423 RTSEMEVENTMULTI hEvtRead;
424
425 /** The validator record for the writer. */
426 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorWrite;
427 /** The validator record for the readers. */
428 R3R0PTRTYPE(PRTLOCKVALRECSHRD) pValidatorRead;
429#if HC_ARCH_BITS == 32
430 /** Size padding. */
431 RTHCPTR HCPtrPadding;
432#endif
433} RTCRITSECTRW;
434AssertCompileSize(RTCRITSECTRW, HC_ARCH_BITS == 32 ? 48 : 64);
435
436/** RTCRITSECTRW::u32Magic value. (Eric Allan Dolphy, Jr.) */
437#define RTCRITSECTRW_MAGIC UINT32_C(0x19280620)
438/** RTCRITSECTRW::u32Magic dead value. */
439#define RTCRITSECTRW_MAGIC_DEAD UINT32_C(0x19640629)
440
[45151]441/** @name RTCRITSECTRW::u64State values.
442 * @note Using RTCSRW instead of RTCRITSECTRW to save space.
443 * @{ */
444#define RTCSRW_CNT_BITS 15
445#define RTCSRW_CNT_MASK UINT64_C(0x00007fff)
[45110]446
[45151]447#define RTCSRW_CNT_RD_SHIFT 0
448#define RTCSRW_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_RD_SHIFT)
449#define RTCSRW_CNT_WR_SHIFT 16
450#define RTCSRW_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_WR_SHIFT)
451
452#define RTCSRW_DIR_SHIFT 31
453#define RTCSRW_DIR_MASK RT_BIT_64(RTCSRW_DIR_SHIFT)
454#define RTCSRW_DIR_READ UINT64_C(0)
455#define RTCSRW_DIR_WRITE UINT64_C(1)
456
457#define RTCSRW_WAIT_CNT_RD_SHIFT 32
458#define RTCSRW_WAIT_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_RD_SHIFT)
459/* #define RTCSRW_WAIT_CNT_WR_SHIFT 48 */
460/* #define RTCSRW_WAIT_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_WR_SHIFT) */
461/** @} */
462
[51940]463#if defined(IN_RING3) || defined(IN_RING0)
[45110]464
465/**
466 * Initialize a critical section.
467 */
[45151]468RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
[45110]469
470/**
471 * Initialize a critical section.
472 *
[45151]473 * @returns IPRT status code.
474 * @param pThis Pointer to the read/write critical section.
[45110]475 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
476 * \#defines.
477 * @param hClass The class (no reference consumed). If NIL, no lock
478 * order validation will be performed on this lock.
479 * @param uSubClass The sub-class. This is used to define lock order
480 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
481 * recommended value here.
482 * @param pszNameFmt Name format string for the lock validator, optional
483 * (NULL). Max length is 32 bytes.
484 * @param ... Format string arguments.
485 */
[57004]486RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
487 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
[45110]488
489/**
490 * Changes the lock validator sub-class of the critical section.
491 *
492 * It is recommended to try make sure that nobody is using this critical section
493 * while changing the value.
494 *
495 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
496 * lock validator isn't compiled in or either of the parameters are
497 * invalid.
[45151]498 * @param pThis Pointer to the read/write critical section.
[45110]499 * @param uSubClass The new sub-class value.
500 */
[45151]501RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
[45110]502
503
504/**
505 * Enter a critical section with shared (read) access.
506 *
[45151]507 * @returns IPRT status code.
508 * @retval VINF_SUCCESS on success.
509 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
510 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
511 * during the operation.
512 * @param pThis Pointer to the read/write critical section.
[45110]513 */
[45151]514RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
[45110]515
516/**
517 * Enter a critical section with shared (read) access.
518 *
[45151]519 * @returns IPRT status code.
[45110]520 * @retval VINF_SUCCESS on success.
521 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]522 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
523 * during the operation.
[45110]524 *
[45151]525 * @param pThis Pointer to the read/write critical section.
[45110]526 * @param uId Where we're entering the section.
[57926]527 * @param SRC_POS The source position where call is being made from.
528 * Use RT_SRC_POS when possible. Optional.
[45110]529 */
[45151]530RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]531
532/**
533 * Try enter a critical section with shared (read) access.
534 *
[45151]535 * @returns IPRT status code.
[45110]536 * @retval VINF_SUCCESS on success.
537 * @retval VERR_SEM_BUSY if the critsect was owned.
538 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]539 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
540 * during the operation.
[45110]541 *
[45151]542 * @param pThis Pointer to the read/write critical section.
[45110]543 */
[45151]544RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
[45110]545
546/**
547 * Try enter a critical section with shared (read) access.
548 *
[45151]549 * @returns IPRT status code.
[45110]550 * @retval VINF_SUCCESS on success.
551 * @retval VERR_SEM_BUSY if the critsect was owned.
552 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]553 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
554 * during the operation.
[45110]555 *
[45151]556 * @param pThis Pointer to the read/write critical section.
[45110]557 * @param uId Where we're entering the section.
[57926]558 * @param SRC_POS The source position where call is being made from.
559 * Use RT_SRC_POS when possible. Optional.
[45110]560 */
[45151]561RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]562
563/**
564 * Leave a critical section held with shared access.
565 *
[45151]566 * @returns IPRT status code.
567 * @param pThis Pointer to the read/write critical section.
[45110]568 */
[45151]569RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
[45110]570
571
572/**
573 * Enter a critical section with exclusive (write) access.
574 *
[45151]575 * @returns IPRT status code.
576 * @retval VINF_SUCCESS on success.
577 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
578 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
579 * during the operation.
580 * @param pThis Pointer to the read/write critical section.
[45110]581 */
[45151]582RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
[45110]583
584/**
585 * Enter a critical section with exclusive (write) access.
586 *
587 * @retval VINF_SUCCESS on success.
588 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]589 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
590 * during the operation.
[45110]591 *
[45151]592 * @param pThis Pointer to the read/write critical section.
[45110]593 * @param uId Where we're entering the section.
[57926]594 * @param SRC_POS The source position where call is being made from.
595 * Use RT_SRC_POS when possible. Optional.
[45110]596 */
[45151]597RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]598
599/**
600 * Try enter a critical section with exclusive (write) access.
601 *
[45151]602 * @returns IPRT status code.
[45110]603 * @retval VINF_SUCCESS on success.
604 * @retval VERR_SEM_BUSY if the critsect was owned.
605 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]606 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
607 * during the operation.
[45110]608 *
[45151]609 * @param pThis Pointer to the read/write critical section.
[45110]610 */
[45151]611RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
[45110]612
613/**
614 * Try enter a critical section with exclusive (write) access.
615 *
[45151]616 * @returns IPRT status code.
[45110]617 * @retval VINF_SUCCESS on success.
618 * @retval VERR_SEM_BUSY if the critsect was owned.
619 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
[45151]620 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
621 * during the operation.
[45110]622 *
[45151]623 * @param pThis Pointer to the read/write critical section.
[45110]624 * @param uId Where we're entering the section.
[57926]625 * @param SRC_POS The source position where call is being made from.
626 * Use RT_SRC_POS when possible. Optional.
[45110]627 */
[45151]628RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
[45110]629
630/**
631 * Leave a critical section held exclusively.
632 *
[45151]633 * @returns IPRT status code; VINF_SUCCESS, VERR_NOT_OWNER, VERR_SEM_DESTROYED,
634 * or VERR_WRONG_ORDER.
635 * @param pThis Pointer to the read/write critical section.
[45110]636 */
[45151]637RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
[45110]638
639
640/**
641 * Deletes a critical section.
642 *
643 * @returns VINF_SUCCESS.
[45151]644 * @param pThis Pointer to the read/write critical section.
[45110]645 */
[45151]646RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
[45110]647
648/**
649 * Checks the caller is the exclusive (write) owner of the critical section.
650 *
[57978]651 * @retval true if owner.
652 * @retval false if not owner.
[45151]653 * @param pThis Pointer to the read/write critical section.
[45110]654 */
[45151]655RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
[45110]656
657/**
[45151]658 * Checks if the caller is one of the read owners of the critical section.
[45110]659 *
660 * @note !CAUTION! This API doesn't work reliably if lock validation isn't
661 * enabled. Meaning, the answer is not trustworhty unless
662 * RT_LOCK_STRICT or RTCRITSECTRW_STRICT was defined at build time.
663 * Also, make sure you do not use RTCRITSECTRW_FLAGS_NO_LOCK_VAL when
664 * creating the semaphore. And finally, if you used a locking class,
665 * don't disable deadlock detection by setting cMsMinDeadlock to
666 * RT_INDEFINITE_WAIT.
667 *
668 * In short, only use this for assertions.
669 *
[45151]670 * @returns @c true if reader, @c false if not.
671 * @param pThis Pointer to the read/write critical section.
[45110]672 * @param fWannaHear What you'd like to hear when lock validation is not
673 * available. (For avoiding asserting all over the
674 * place.)
675 */
[45151]676RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
[45110]677
678/**
679 * Gets the write recursion count.
680 *
681 * @returns The write recursion count (0 if bad critsect).
[45151]682 * @param pThis Pointer to the read/write critical section.
[45110]683 */
[45151]684RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
[45110]685
686/**
687 * Gets the read recursion count of the current writer.
688 *
689 * @returns The read recursion count (0 if bad critsect).
[45151]690 * @param pThis Pointer to the read/write critical section.
[45110]691 */
[45151]692RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
[45110]693
694/**
695 * Gets the current number of reads.
696 *
697 * This includes all read recursions, so it might be higher than the number of
698 * read owners. It does not include reads done by the current writer.
699 *
700 * @returns The read count (0 if bad critsect).
[45151]701 * @param pThis Pointer to the read/write critical section.
[45110]702 */
[45151]703RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
[45110]704
[51940]705#endif /* IN_RING3 || IN_RING0 */
[45110]706
707/**
708 * Checks if a critical section is initialized or not.
709 *
[57978]710 * @retval true if initialized.
711 * @retval false if not initialized.
[45151]712 * @param pThis Pointer to the read/write critical section.
[45110]713 */
[45151]714DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
[45110]715{
[45151]716 return pThis->u32Magic == RTCRITSECTRW_MAGIC;
[45110]717}
718
719/* Lock strict build: Remap the three enter calls to the debug versions. */
720#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
[76557]721# ifdef IPRT_INCLUDED_asm_h
[45151]722# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
723# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
724# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
725# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
[45110]726# else
[45151]727# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, 0, RT_SRC_POS)
728# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, 0, RT_SRC_POS)
729# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, 0, RT_SRC_POS)
730# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, 0, RT_SRC_POS)
[45110]731# endif
732#endif
733
734/* Strict lock order: Automatically classify locks by init location. */
735#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
[45151]736# define RTCritSectRwInit(a_pThis) \
737 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
[45110]738 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
739 RTLOCKVAL_SUB_CLASS_NONE, NULL)
740#endif
741
[1]742/** @} */
743
[20374]744RT_C_DECLS_END
[1]745
[76585]746#endif /* !IPRT_INCLUDED_critsect_h */
[1]747
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