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
Line 
1/** @file
2 * IPRT - Critical Sections.
3 */
4
5/*
6 * Copyright (C) 2006-2019 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef IPRT_INCLUDED_critsect_h
27#define IPRT_INCLUDED_critsect_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/cdefs.h>
33#include <iprt/types.h>
34#include <iprt/assert.h>
35#if defined(IN_RING3) || defined(IN_RING0)
36# include <iprt/thread.h>
37#endif
38#ifdef RT_LOCK_STRICT_ORDER
39# include <iprt/lockvalidator.h>
40#endif
41
42RT_C_DECLS_BEGIN
43
44/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
45 *
46 * "Critical section" synchronization primitives can be used to
47 * protect a section of code or data to which access must be exclusive;
48 * only one thread can hold access to a critical section at one time.
49 *
50 * A critical section is a fast recursive write lock; if the critical
51 * section is not acquired, then entering it is fast (requires no system
52 * call). IPRT uses the Windows terminology here; on other platform, this
53 * might be called a "futex" or a "fast mutex". As opposed to IPRT
54 * "fast mutexes" (see @ref grp_rt_sems_fast_mutex ), critical sections
55 * are recursive.
56 *
57 * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
58 * and RTCritSectLeave to acquire and release access.
59 *
60 * For an overview of all types of synchronization primitives provided
61 * by IPRT (event, mutex/fast mutex/read-write mutex semaphores), see
62 * @ref grp_rt_sems .
63 *
64 * @ingroup grp_rt
65 * @{
66 */
67
68/**
69 * Critical section.
70 */
71typedef struct RTCRITSECT
72{
73 /** Magic used to validate the section state.
74 * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
75 volatile uint32_t u32Magic;
76 /** Number of lockers.
77 * -1 if the section is free. */
78 volatile int32_t cLockers;
79 /** The owner thread. */
80 volatile RTNATIVETHREAD NativeThreadOwner;
81 /** Number of nested enter operations performed.
82 * Greater or equal to 1 if owned, 0 when free.
83 */
84 volatile int32_t cNestings;
85 /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
86 uint32_t fFlags;
87 /** The semaphore to block on. */
88 RTSEMEVENT EventSem;
89 /** Lock validator record. Only used in strict builds. */
90 R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
91 /** Alignmnet padding. */
92 RTHCPTR Alignment;
93} RTCRITSECT;
94AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
95
96/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
97#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
98
99/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags
100 * @{ */
101/** If set, nesting(/recursion) is not allowed. */
102#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
103/** Disables lock validation. */
104#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
105/** Bootstrap hack for use with certain memory allocator locks only! */
106#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
107/** If set, the critical section becomes a dummy that doesn't serialize any
108 * threads. This flag can only be set at creation time.
109 *
110 * The intended use is avoiding lots of conditional code where some component
111 * might or might not require entering a critical section before access. */
112#define RTCRITSECT_FLAGS_NOP UINT32_C(0x00000008)
113/** Indicates that this is a ring-0 critical section. */
114#define RTCRITSECT_FLAGS_RING0 UINT32_C(0x00000010)
115/** @} */
116
117
118#if defined(IN_RING3) || defined(IN_RING0)
119
120/**
121 * Initialize a critical section.
122 */
123RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
124
125/**
126 * Initialize a critical section.
127 *
128 * @returns iprt status code.
129 * @param pCritSect Pointer to the critical section structure.
130 * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
131 * \#defines.
132 * @param hClass The class (no reference consumed). If NIL, no lock
133 * order validation will be performed on this lock.
134 * @param uSubClass The sub-class. This is used to define lock order
135 * within a class. RTLOCKVAL_SUB_CLASS_NONE is the
136 * recommended value here.
137 * @param pszNameFmt Name format string for the lock validator, optional
138 * (NULL). Max length is 32 bytes.
139 * @param ... Format string arguments.
140 */
141RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
142 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
143
144/**
145 * Changes the lock validator sub-class of the critical section.
146 *
147 * It is recommended to try make sure that nobody is using this critical section
148 * while changing the value.
149 *
150 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
151 * lock validator isn't compiled in or either of the parameters are
152 * invalid.
153 * @param pCritSect The critical section.
154 * @param uSubClass The new sub-class value.
155 */
156RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
157
158/**
159 * Enter a critical section.
160 *
161 * @returns VINF_SUCCESS on success.
162 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
163 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
164 * during the operation.
165 * @param pCritSect The critical section.
166 */
167RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
168
169/**
170 * Enter a critical section.
171 *
172 * @returns IPRT status code.
173 * @retval VINF_SUCCESS on success.
174 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
175 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
176 * during the operation.
177 *
178 * @param pCritSect The critical section.
179 * @param uId Where we're entering the section.
180 * @param SRC_POS The source position where call is being made from.
181 * Use RT_SRC_POS when possible. Optional.
182 */
183RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
184
185/**
186 * Try enter a critical section.
187 *
188 * @retval VINF_SUCCESS on success.
189 * @retval VERR_SEM_BUSY if the critsect was owned.
190 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
191 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
192 * during the operation.
193 *
194 * @param pCritSect The critical section.
195 */
196RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
197
198/**
199 * Try enter a critical section.
200 *
201 * @retval VINF_SUCCESS on success.
202 * @retval VERR_SEM_BUSY if the critsect was owned.
203 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
204 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
205 * during the operation.
206 *
207 * @param pCritSect The critical section.
208 * @param uId Where we're entering the section.
209 * @param SRC_POS The source position where call is being made from.
210 * Use RT_SRC_POS when possible. Optional.
211 */
212RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
213
214# ifdef IN_RING3 /* Crazy APIs: ring-3 only. */
215
216/**
217 * Enter multiple critical sections.
218 *
219 * This function will enter ALL the specified critical sections before returning.
220 *
221 * @returns VINF_SUCCESS on success.
222 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
223 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
224 * during the operation.
225 * @param cCritSects Number of critical sections in the array.
226 * @param papCritSects Array of critical section pointers.
227 *
228 * @remark Please note that this function will not necessarily come out favourable in a
229 * fight with other threads which are using the normal RTCritSectEnter() function.
230 * Therefore, avoid having to enter multiple critical sections!
231 */
232RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
233
234/**
235 * Enter multiple critical sections.
236 *
237 * This function will enter ALL the specified critical sections before returning.
238 *
239 * @returns VINF_SUCCESS on success.
240 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
241 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
242 * during the operation.
243 *
244 * @param cCritSects Number of critical sections in the array.
245 * @param papCritSects Array of critical section pointers.
246 * @param uId Where we're entering the section.
247 * @param SRC_POS The source position where call is being made from.
248 * Use RT_SRC_POS when possible. Optional.
249 *
250 * @remark See RTCritSectEnterMultiple().
251 */
252RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL);
253
254# endif /* IN_RING3 */
255
256/**
257 * Leave a critical section.
258 *
259 * @returns VINF_SUCCESS.
260 * @param pCritSect The critical section.
261 */
262RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);
263
264/**
265 * Leave multiple critical sections.
266 *
267 * @returns VINF_SUCCESS.
268 * @param cCritSects Number of critical sections in the array.
269 * @param papCritSects Array of critical section pointers.
270 */
271RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
272
273/**
274 * Deletes a critical section.
275 *
276 * @returns VINF_SUCCESS.
277 * @param pCritSect The critical section.
278 */
279RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);
280
281/**
282 * Checks the caller is the owner of the critical section.
283 *
284 * @returns true if owner.
285 * @returns false if not owner.
286 * @param pCritSect The critical section.
287 */
288DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
289{
290 return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
291}
292
293#endif /* IN_RING3 || IN_RING0 */
294
295/**
296 * Checks the section is owned by anyone.
297 *
298 * @returns true if owned.
299 * @returns false if not owned.
300 * @param pCritSect The critical section.
301 */
302DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
303{
304 return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
305}
306
307/**
308 * Gets the thread id of the critical section owner.
309 *
310 * @returns Thread id of the owner thread if owned.
311 * @returns NIL_RTNATIVETHREAD is not owned.
312 * @param pCritSect The critical section.
313 */
314DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
315{
316 return pCritSect->NativeThreadOwner;
317}
318
319/**
320 * Checks if a critical section is initialized or not.
321 *
322 * @returns true if initialized.
323 * @returns false if not initialized.
324 * @param pCritSect The critical section.
325 */
326DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
327{
328 return pCritSect->u32Magic == RTCRITSECT_MAGIC;
329}
330
331/**
332 * Gets the recursion depth.
333 *
334 * @returns The recursion depth.
335 * @param pCritSect The Critical section
336 */
337DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
338{
339 return pCritSect->cNestings;
340}
341
342/**
343 * Gets the waiter count
344 *
345 * @returns The waiter count
346 * @param pCritSect The Critical section
347 */
348DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
349{
350 return pCritSect->cLockers;
351}
352
353/* Lock strict build: Remap the three enter calls to the debug versions. */
354#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
355# ifdef IPRT_INCLUDED_asm_h
356# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
357# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
358# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
359# else
360# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS)
361# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS)
362# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 0, RT_SRC_POS)
363# endif
364#endif
365
366/* Strict lock order: Automatically classify locks by init location. */
367#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
368# define RTCritSectInit(pCritSect) \
369 RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
370 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
371 RTLOCKVAL_SUB_CLASS_NONE, NULL)
372#endif
373
374/** @} */
375
376
377
378/** @defgroup grp_rt_critsectrw RTCritSectRw - Read/Write Critical Sections
379 * @ingroup grp_rt
380 * @{
381 */
382
383/**
384 * 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
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)
446
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
463#if defined(IN_RING3) || defined(IN_RING0)
464
465/**
466 * Initialize a critical section.
467 */
468RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
469
470/**
471 * Initialize a critical section.
472 *
473 * @returns IPRT status code.
474 * @param pThis Pointer to the read/write critical section.
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 */
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);
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.
498 * @param pThis Pointer to the read/write critical section.
499 * @param uSubClass The new sub-class value.
500 */
501RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
502
503
504/**
505 * Enter a critical section with shared (read) access.
506 *
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.
513 */
514RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
515
516/**
517 * Enter a critical section with shared (read) access.
518 *
519 * @returns IPRT status code.
520 * @retval VINF_SUCCESS on success.
521 * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
522 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
523 * during the operation.
524 *
525 * @param pThis Pointer to the read/write critical section.
526 * @param uId Where we're entering the section.
527 * @param SRC_POS The source position where call is being made from.
528 * Use RT_SRC_POS when possible. Optional.
529 */
530RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
531
532/**
533 * Try enter a critical section with shared (read) access.
534 *
535 * @returns IPRT status code.
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.)
539 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
540 * during the operation.
541 *
542 * @param pThis Pointer to the read/write critical section.
543 */
544RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
545
546/**
547 * Try enter a critical section with shared (read) access.
548 *
549 * @returns IPRT status code.
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.)
553 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
554 * during the operation.
555 *
556 * @param pThis Pointer to the read/write critical section.
557 * @param uId Where we're entering the section.
558 * @param SRC_POS The source position where call is being made from.
559 * Use RT_SRC_POS when possible. Optional.
560 */
561RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
562
563/**
564 * Leave a critical section held with shared access.
565 *
566 * @returns IPRT status code.
567 * @param pThis Pointer to the read/write critical section.
568 */
569RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
570
571
572/**
573 * Enter a critical section with exclusive (write) access.
574 *
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.
581 */
582RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
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.)
589 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
590 * during the operation.
591 *
592 * @param pThis Pointer to the read/write critical section.
593 * @param uId Where we're entering the section.
594 * @param SRC_POS The source position where call is being made from.
595 * Use RT_SRC_POS when possible. Optional.
596 */
597RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
598
599/**
600 * Try enter a critical section with exclusive (write) access.
601 *
602 * @returns IPRT status code.
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.)
606 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
607 * during the operation.
608 *
609 * @param pThis Pointer to the read/write critical section.
610 */
611RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
612
613/**
614 * Try enter a critical section with exclusive (write) access.
615 *
616 * @returns IPRT status code.
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.)
620 * @retval VERR_SEM_DESTROYED if the critical section is delete before or
621 * during the operation.
622 *
623 * @param pThis Pointer to the read/write critical section.
624 * @param uId Where we're entering the section.
625 * @param SRC_POS The source position where call is being made from.
626 * Use RT_SRC_POS when possible. Optional.
627 */
628RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
629
630/**
631 * Leave a critical section held exclusively.
632 *
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.
636 */
637RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
638
639
640/**
641 * Deletes a critical section.
642 *
643 * @returns VINF_SUCCESS.
644 * @param pThis Pointer to the read/write critical section.
645 */
646RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
647
648/**
649 * Checks the caller is the exclusive (write) owner of the critical section.
650 *
651 * @retval true if owner.
652 * @retval false if not owner.
653 * @param pThis Pointer to the read/write critical section.
654 */
655RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
656
657/**
658 * Checks if the caller is one of the read owners of the critical section.
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 *
670 * @returns @c true if reader, @c false if not.
671 * @param pThis Pointer to the read/write critical section.
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 */
676RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
677
678/**
679 * Gets the write recursion count.
680 *
681 * @returns The write recursion count (0 if bad critsect).
682 * @param pThis Pointer to the read/write critical section.
683 */
684RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
685
686/**
687 * Gets the read recursion count of the current writer.
688 *
689 * @returns The read recursion count (0 if bad critsect).
690 * @param pThis Pointer to the read/write critical section.
691 */
692RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
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).
701 * @param pThis Pointer to the read/write critical section.
702 */
703RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
704
705#endif /* IN_RING3 || IN_RING0 */
706
707/**
708 * Checks if a critical section is initialized or not.
709 *
710 * @retval true if initialized.
711 * @retval false if not initialized.
712 * @param pThis Pointer to the read/write critical section.
713 */
714DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
715{
716 return pThis->u32Magic == RTCRITSECTRW_MAGIC;
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)
721# ifdef IPRT_INCLUDED_asm_h
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)
726# else
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)
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)
736# define RTCritSectRwInit(a_pThis) \
737 RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
738 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
739 RTLOCKVAL_SUB_CLASS_NONE, NULL)
740#endif
741
742/** @} */
743
744RT_C_DECLS_END
745
746#endif /* !IPRT_INCLUDED_critsect_h */
747
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle
ContactPrivacy/Do Not Sell My InfoTerms of Use