6 * Copyright (C) 2006-2016 Oracle Corporation
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.
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.
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.
26 #ifndef ___iprt_semaphore_h
27 #define ___iprt_semaphore_h
29 #include <iprt/cdefs.h>
30 #include <iprt/types.h>
31 #if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3)
32 # include <iprt/lockvalidator.h>
38 /** @defgroup grp_rt_sems RTSem - Semaphores
40 * This module implements all kinds of event and mutex semaphores; in addition
41 * to these, IPRT implements "critical sections", which are fast recursive
42 * mutexes (see @ref grp_rt_critsect ). C++ users may find @ref grp_rt_cpp_lock
50 /** @name Generic Semaphore Wait Flags.
52 * @remarks Exactly one of RTSEMWAIT_FLAGS_RELATIVE and
53 * RTSEMWAIT_FLAGS_ABSOLUTE must be set, unless
54 * RTSEMWAIT_FLAGS_INDEFINITE is used.
56 * Exactly one of RTSEMWAIT_FLAGS_NANOSECS and
57 * RTSEMWAIT_FLAGS_MILLISECS must be set, unless
58 * RTSEMWAIT_FLAGS_INDEFINITE is used.
60 * Exactly one of RTSEMWAIT_FLAGS_RESUME and RTSEMWAIT_FLAGS_NORESUME
63 * The interruptible vs resume stuff is ring-0 vs ring-3 semantics.
66 /** The timeout is relative. */
67 #define RTSEMWAIT_FLAGS_RELATIVE RT_BIT_32(0)
68 /** The timeout is absolute. */
69 #define RTSEMWAIT_FLAGS_ABSOLUTE RT_BIT_32(1)
70 /** The timeout is specified in nanoseconds. */
71 #define RTSEMWAIT_FLAGS_NANOSECS RT_BIT_32(2)
72 /** The timeout is specified in milliseconds. */
73 #define RTSEMWAIT_FLAGS_MILLISECS RT_BIT_32(3)
75 * The relative/absolute and nano-/millisecond flags are ignored. */
76 #define RTSEMWAIT_FLAGS_INDEFINITE RT_BIT_32(4)
77 /** Mask covering the time related bits. */
78 #define RTSEMWAIT_FLAGS_TIME_MASK UINT32_C(0x0000001f)
80 /** Interruptible wait. */
81 #define RTSEMWAIT_FLAGS_INTERRUPTIBLE RT_BIT_32(5)
82 /** No automatic resume, same as interruptible. */
83 #define RTSEMWAIT_FLAGS_NORESUME RTSEMWAIT_FLAGS_INTERRUPTIBLE
84 /** Uninterruptible wait. */
85 #define RTSEMWAIT_FLAGS_UNINTERRUPTIBLE RT_BIT_32(6)
86 /** Resume on interrupt, same as uninterruptible. */
87 #define RTSEMWAIT_FLAGS_RESUME RTSEMWAIT_FLAGS_UNINTERRUPTIBLE
89 /** Macro for validate the flags. */
90 #define RTSEMWAIT_FLAGS_ARE_VALID(fFlags) \
91 ( !((fFlags) & UINT32_C(0xffffff80)) \
92 && ( ((fFlags) & RTSEMWAIT_FLAGS_INDEFINITE) \
93 ? ( (((fFlags) & UINT32_C(0x20))) ^ (((fFlags) >> 1) & UINT32_C(0x20)) ) == UINT32_C(0x20) \
94 : ( (((fFlags) & UINT32_C(0x25))) ^ (((fFlags) >> 1) & UINT32_C(0x25)) ) == UINT32_C(0x25) ))
99 /** @defgroup grp_rt_sems_event RTSemEvent - Single Release Event Semaphores
101 * Event semaphores can be used for inter-thread communication when one thread
102 * wants to notify another thread that something happened. A thread can block
103 * ("wait") on an event semaphore until it is signalled by another thread; see
104 * RTSemEventCreate, RTSemEventSignal and RTSemEventWait.
109 * Create an event semaphore.
111 * @returns iprt status code.
112 * @param phEventSem Where to store the handle to the newly created
115 RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem
);
118 * Create an event semaphore.
120 * @returns iprt status code.
121 * @param phEventSem Where to store the handle to the newly created
123 * @param fFlags Flags, any combination of the
124 * RTSEMEVENT_FLAGS_XXX \#defines.
125 * @param hClass The class (no reference consumed). Since we
126 * don't do order checks on event semaphores, the
127 * use of the class is limited to controlling the
128 * timeout threshold for deadlock detection.
129 * @param pszNameFmt Name format string for the lock validator,
130 * optional (NULL). Max length is 32 bytes.
131 * @param ... Format string arguments.
133 RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem
, uint32_t fFlags
, RTLOCKVALCLASS hClass
,
134 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
136 /** @name RTSemMutexCreateEx flags
138 /** Disables lock validation. */
139 #define RTSEMEVENT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
140 /** Bootstrap hack for use with certain memory allocator locks only! */
141 #define RTSEMEVENT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
145 * Destroy an event semaphore.
147 * @returns iprt status code.
148 * @param hEventSem Handle of the event semaphore. NIL_RTSEMEVENT
149 * is quietly ignored (VINF_SUCCESS).
151 RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem
);
154 * Signal an event semaphore.
156 * The event semaphore will be signaled and automatically reset after exactly
157 * one thread have successfully returned from RTSemEventWait() after
158 * waiting/polling on that semaphore.
160 * @returns iprt status code.
161 * @param hEventSem The event semaphore to signal.
163 * @remarks ring-0: This works when preemption is disabled. However it is
164 * system specific whether it works in interrupt context or with
165 * interrupts disabled.
167 RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem
);
170 * Wait for the event semaphore to be signaled, resume on interruption.
172 * This function will resume if the wait is interrupted by an async system event
173 * (like a unix signal) or similar.
175 * @returns iprt status code.
176 * Will not return VERR_INTERRUPTED.
177 * @param hEventSem The event semaphore to wait on.
178 * @param cMillies Number of milliseconds to wait.
180 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem
, RTMSINTERVAL cMillies
);
183 * Wait for the event semaphore to be signaled, return on interruption.
185 * This function will not resume the wait if interrupted.
187 * @returns iprt status code.
188 * @param hEventSem The event semaphore to wait on.
189 * @param cMillies Number of milliseconds to wait.
191 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem
, RTMSINTERVAL cMillies
);
194 * Extended API for waiting on an event semaphore to be signaled.
196 * @returns IPRT status code.
197 * @param hEventSem The event semaphore to wait on.
198 * @param fFlags Combination of RTSEMWAIT_FLAGS_XXX.
199 * @param uTimeout The timeout, ignored if
200 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
201 * Whether this is absolute or relative,
202 * milliseconds or nanoseconds depends on the @a
203 * fFlags value. Do not pass RT_INDEFINITE_WAIT
204 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
206 RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem
, uint32_t fFlags
, uint64_t uTimeout
);
209 * Debug version of RTSemEventWaitEx that tracks the location.
211 * @returns IPRT status code, see RTSemEventWaitEx.
212 * @param hEventSem The event semaphore to wait on.
213 * @param fFlags See RTSemEventWaitEx.
214 * @param uTimeout See RTSemEventWaitEx.
215 * @param uId Some kind of locking location ID. Typically a
216 * return address up the stack. Optional (0).
217 * @param SRC_POS The source position where call is being made
218 * from. Use RT_SRC_POS when possible. Optional.
220 RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem
, uint32_t fFlags
, uint64_t uTimeout
,
221 RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
224 * Gets the best timeout resolution that RTSemEventWaitEx can do.
226 * @returns The resolution in nanoseconds.
228 RTDECL(uint32_t) RTSemEventGetResolution(void);
231 * Sets the signaller thread to one specific thread.
233 * This is only used for validating usage and deadlock detection. When used
234 * after calls to RTSemEventAddSignaller, the specified thread will be the only
237 * @param hEventSem The event semaphore.
238 * @param hThread The thread that will signal it. Pass
239 * NIL_RTTHREAD to indicate that there is no
240 * special signalling thread.
242 RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem
, RTTHREAD hThread
);
245 * To add more signalling threads.
247 * First call RTSemEventSetSignaller then add further threads with this.
249 * @param hEventSem The event semaphore.
250 * @param hThread The thread that will signal it. NIL_RTTHREAD is
253 RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem
, RTTHREAD hThread
);
256 * To remove a signalling thread.
258 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
260 * @param hEventSem The event semaphore.
261 * @param hThread A previously added thread.
263 RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem
, RTTHREAD hThread
);
268 /** @defgroup grp_rt_sems_event_multi RTSemEventMulti - Multiple Release Event Semaphores
270 * A variant of @ref grp_rt_sems_event where all threads will be unblocked when
271 * signalling the semaphore.
276 * Creates a multiple release event semaphore.
278 * @returns iprt status code.
279 * @param phEventMultiSem Where to store the handle to the newly created
280 * multiple release event semaphore.
282 RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem
);
285 * Creates a multiple release event semaphore.
287 * @returns iprt status code.
288 * @param phEventMultiSem Where to store the handle to the newly created
289 * multiple release event semaphore.
290 * @param fFlags Flags, any combination of the
291 * RTSEMEVENTMULTI_FLAGS_XXX \#defines.
292 * @param hClass The class (no reference consumed). Since we
293 * don't do order checks on event semaphores, the
294 * use of the class is limited to controlling the
295 * timeout threshold for deadlock detection.
296 * @param pszNameFmt Name format string for the lock validator,
297 * optional (NULL). Max length is 32 bytes.
298 * @param ... Format string arguments.
300 RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem
, uint32_t fFlags
, RTLOCKVALCLASS hClass
,
301 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
303 /** @name RTSemMutexCreateEx flags
305 /** Disables lock validation. */
306 #define RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
310 * Destroy an event multi semaphore.
312 * @returns iprt status code.
313 * @param hEventMultiSem The multiple release event semaphore. NIL is
314 * quietly ignored (VINF_SUCCESS).
316 RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem
);
319 * Signal an event multi semaphore.
321 * @returns iprt status code.
322 * @param hEventMultiSem The multiple release event semaphore.
324 * @remarks ring-0: This works when preemption is disabled. However it is
325 * system specific whether it works in interrupt context or with
326 * interrupts disabled.
328 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem
);
331 * Resets an event multi semaphore to non-signaled state.
333 * @returns iprt status code.
334 * @param hEventMultiSem The multiple release event semaphore.
336 RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem
);
339 * Wait for the event multi semaphore to be signaled, resume on interruption.
341 * This function will resume if the wait is interrupted by an async
342 * system event (like a unix signal) or similar.
344 * @returns iprt status code.
345 * Will not return VERR_INTERRUPTED.
346 * @param hEventMultiSem The multiple release event semaphore.
347 * @param cMillies Number of milliseconds to wait.
349 RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem
, RTMSINTERVAL cMillies
);
352 * Wait for the event multi semaphore to be signaled, return on interruption.
354 * This function will not resume the wait if interrupted.
356 * @returns iprt status code.
357 * @param hEventMultiSem The multiple release event semaphore.
358 * @param cMillies Number of milliseconds to wait.
359 * @todo Rename to RTSemEventMultiWaitIntr since it is mainly for
360 * ring-0 consumption.
362 RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem
, RTMSINTERVAL cMillies
);
365 * Extended API for waiting on an event semaphore to be signaled.
367 * @returns IPRT status code.
368 * @param hEventMultiSem The multiple release event semaphore to wait
370 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
371 * @param uTimeout The timeout, ignored if
372 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
373 * Whether this is absolute or relative,
374 * milliseconds or nanoseconds depends on the @a
375 * fFlags value. Do not pass RT_INDEFINITE_WAIT
376 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
378 RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem
, uint32_t fFlags
, uint64_t uTimeout
);
381 * Debug version of RTSemEventMultiWaitEx that tracks the location.
383 * @returns IPRT status code, see RTSemEventMultiWaitEx.
384 * @param hEventMultiSem The multiple release event semaphore handle.
385 * @param fFlags See RTSemEventMultiWaitEx.
386 * @param uTimeout See RTSemEventMultiWaitEx.
387 * @param uId Some kind of locking location ID. Typically a
388 * return address up the stack. Optional (0).
389 * @param SRC_POS The source position where call is being made
390 * from. Use RT_SRC_POS when possible. Optional.
392 RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem
, uint32_t fFlags
, uint64_t uTimeout
,
393 RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
396 * Gets the best timeout resolution that RTSemEventMultiWaitEx can do.
398 * @returns The resolution in nanoseconds.
400 RTDECL(uint32_t) RTSemEventMultiGetResolution(void);
403 * Sets the signaller thread to one specific thread.
405 * This is only used for validating usage and deadlock detection. When used
406 * after calls to RTSemEventAddSignaller, the specified thread will be the only
409 * @param hEventMultiSem The multiple release event semaphore.
410 * @param hThread The thread that will signal it. Pass
411 * NIL_RTTHREAD to indicate that there is no
412 * special signalling thread.
414 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem
, RTTHREAD hThread
);
417 * To add more signalling threads.
419 * First call RTSemEventSetSignaller then add further threads with this.
421 * @param hEventMultiSem The multiple release event semaphore.
422 * @param hThread The thread that will signal it. NIL_RTTHREAD is
425 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem
, RTTHREAD hThread
);
428 * To remove a signalling thread.
430 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
432 * @param hEventMultiSem The multiple release event semaphore.
433 * @param hThread A previously added thread.
435 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem
, RTTHREAD hThread
);
440 /** @defgroup grp_rt_sems_mutex RTSemMutex - Mutex semaphores.
442 * Mutex semaphores protect a section of code or data to which access must be
443 * exclusive. Only one thread can hold access to a critical section at one
444 * time. See RTSemMutexCreate, RTSemMutexRequest and RTSemMutexRelease.
446 * @remarks These are less efficient than "fast mutexes" and "critical
447 * sections", which IPRT implements as well; see @ref
448 * grp_rt_sems_fast_mutex and @ref grp_rt_critsect .
453 * Create a mutex semaphore.
455 * @returns iprt status code.
456 * @param phMutexSem Where to store the mutex semaphore handle.
458 RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem
);
461 * Creates a read/write semaphore.
463 * @returns iprt status code.
464 * @param phMutexSem Where to store the handle to the newly created
466 * @param fFlags Flags, any combination of the
467 * RTSEMMUTEX_FLAGS_XXX \#defines.
468 * @param hClass The class (no reference consumed). If NIL, no
469 * lock order validation will be performed on this
471 * @param uSubClass The sub-class. This is used to define lock
472 * order within a class. RTLOCKVAL_SUB_CLASS_NONE
473 * is the recommended value here.
474 * @param pszNameFmt Name format string for the lock validator,
475 * optional (NULL). Max length is 32 bytes.
476 * @param ... Format string arguments.
478 RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem
, uint32_t fFlags
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
,
479 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
481 /** @name RTSemMutexCreateEx flags
483 /** Disables lock validation. */
484 #define RTSEMMUTEX_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
489 * Destroy a mutex semaphore.
491 * @returns iprt status code.
492 * @param hMutexSem The mutex semaphore to destroy. NIL is quietly
493 * ignored (VINF_SUCCESS).
495 RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem
);
498 * Changes the lock validator sub-class of the mutex semaphore.
500 * It is recommended to try make sure that nobody is using this semaphore while
501 * changing the value.
503 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
504 * lock validator isn't compiled in or either of the parameters are
506 * @param hMutexSem The handle to the mutex semaphore.
507 * @param uSubClass The new sub-class value.
509 RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem
, uint32_t uSubClass
);
512 * Request ownership of a mutex semaphore, resume on interruption.
514 * This function will resume if the wait is interrupted by an async
515 * system event (like a unix signal) or similar.
517 * The same thread may request a mutex semaphore multiple times,
518 * a nested counter is kept to make sure it's released on the right
519 * RTSemMutexRelease() call.
521 * @returns iprt status code.
522 * Will not return VERR_INTERRUPTED.
523 * @param hMutexSem The mutex semaphore to request ownership over.
524 * @param cMillies The number of milliseconds to wait.
526 RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem
, RTMSINTERVAL cMillies
);
529 * Request ownership of a mutex semaphore, return on interruption.
531 * This function will not resume the wait if interrupted.
533 * The same thread may request a mutex semaphore multiple times,
534 * a nested counter is kept to make sure it's released on the right
535 * RTSemMutexRelease() call.
537 * @returns iprt status code.
538 * @param hMutexSem The mutex semaphore to request ownership over.
539 * @param cMillies The number of milliseconds to wait.
541 RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem
, RTMSINTERVAL cMillies
);
544 * Debug version of RTSemMutexRequest that tracks the location.
546 * @returns iprt status code.
547 * Will not return VERR_INTERRUPTED.
548 * @param hMutexSem The mutex semaphore to request ownership over.
549 * @param cMillies The number of milliseconds to wait.
550 * @param uId Some kind of locking location ID. Typically a
551 * return address up the stack. Optional (0).
552 * @param SRC_POS The source position where call is being made
553 * from. Use RT_SRC_POS when possible. Optional.
555 RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem
, RTMSINTERVAL cMillies
, RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
558 * Debug version of RTSemMutexRequestNoResume that tracks the location.
560 * @returns iprt status code.
561 * @param hMutexSem The mutex semaphore to request ownership over.
562 * @param cMillies The number of milliseconds to wait.
563 * @param uId Some kind of locking location ID. Typically a
564 * return address up the stack. Optional (0).
565 * @param SRC_POS The source position where call is being made
566 * from. Use RT_SRC_POS when possible. Optional.
568 RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem
, RTMSINTERVAL cMillies
, RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
571 * Request ownership of a mutex semaphore, extended edition.
573 * The same thread may request a mutex semaphore multiple times,
574 * a nested counter is kept to make sure it's released on the right
575 * RTSemMutexRelease() call.
577 * @returns iprt status code.
578 * @param hMutexSem The mutex semaphore to request ownership over.
579 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
580 * @param uTimeout The timeout, ignored if
581 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
582 * Whether this is absolute or relative,
583 * milliseconds or nanoseconds depends on the @a
584 * fFlags value. Do not pass RT_INDEFINITE_WAIT
585 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
587 RTDECL(int) RTSemMutexRequestEx(RTSEMMUTEX hMutexSem
, uint32_t fFlags
, uint64_t uTimeout
);
590 * Debug version of RTSemMutexRequestEx that tracks the location.
592 * @returns iprt status code.
593 * @param hMutexSem The mutex semaphore to request ownership over.
594 * @param fFlags See RTSemMutexRequestEx.
595 * @param uTimeout See RTSemMutexRequestEx.
596 * @param uId Some kind of locking location ID. Typically a
597 * return address up the stack. Optional (0).
598 * @param SRC_POS The source position where call is being made
599 * from. Use RT_SRC_POS when possible. Optional.
601 RTDECL(int) RTSemMutexRequestExDebug(RTSEMMUTEX hMutexSem
, uint32_t fFlags
, uint64_t uTimeout
,
602 RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
605 * Release the ownership of a mutex semaphore.
607 * @returns iprt status code.
608 * @param hMutexSem The mutex to release the ownership of. It goes
609 * without saying the the calling thread must own
612 RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem
);
615 * Checks if the mutex semaphore is owned or not.
617 * @returns true if owned, false if not.
618 * @param hMutexSem The mutex semaphore.
620 RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem
);
622 /* Strict build: Remap the two request calls to the debug versions. */
623 #if defined(RT_STRICT) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
624 # ifdef ___iprt_asm_h
625 # define RTSemMutexRequest(hMutexSem, cMillies) RTSemMutexRequestDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
626 # define RTSemMutexRequestNoResume(hMutexSem, cMillies) RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
627 # define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout) RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
629 # define RTSemMutexRequest(hMutexSem, cMillies) RTSemMutexRequestDebug((hMutexSem), (cMillies), 0, RT_SRC_POS)
630 # define RTSemMutexRequestNoResume(hMutexSem, cMillies) RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), 0, RT_SRC_POS)
631 # define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout) RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), 0, RT_SRC_POS)
635 /* Strict lock order: Automatically classify locks by init location. */
636 #if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
637 # define RTSemMutexCreate(phMutexSem) \
638 RTSemMutexCreateEx((phMutexSem), 0 /*fFlags*/, \
639 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
640 RTLOCKVAL_SUB_CLASS_NONE, NULL)
646 /** @defgroup grp_rt_sems_fast_mutex RTSemFastMutex - Fast Mutex Semaphores
648 * Fast mutexes work like regular mutexes in that they allow only a single
649 * thread access to a critical piece of code or data. As opposed to mutexes,
650 * they require no syscall if the fast mutex is not held (like critical
651 * sections). Unlike critical sections however, they are *not* recursive.
653 * @remarks The fast mutexes has sideeffects on IRQL on Windows hosts. So use
654 * with care and test on windows with driver verifier.
659 * Create a fast mutex semaphore.
661 * @returns iprt status code.
662 * @param phFastMtx Where to store the handle to the newly created
663 * fast mutex semaphore.
665 * @remarks Fast mutex semaphores are not recursive.
667 RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx
);
670 * Destroy a fast mutex semaphore.
672 * @returns iprt status code.
673 * @param hFastMtx Handle to the fast mutex semaphore. NIL is
674 * quietly ignored (VINF_SUCCESS).
676 RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx
);
679 * Request ownership of a fast mutex semaphore.
681 * The same thread may request a mutex semaphore multiple times,
682 * a nested counter is kept to make sure it's released on the right
683 * RTSemMutexRelease() call.
685 * @returns iprt status code.
686 * @param hFastMtx Handle to the fast mutex semaphore.
688 RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx
);
691 * Release the ownership of a fast mutex semaphore.
693 * @returns iprt status code.
694 * @param hFastMtx Handle to the fast mutex semaphore. It goes
695 * without saying the the calling thread must own
698 RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx
);
703 /** @defgroup grp_rt_sems_spin_mutex RTSemSpinMutex - Spinning Mutex Semaphores
705 * A very adaptive variant of mutex semaphore that is tailored for the ring-0
711 * Creates a spinning mutex semaphore.
713 * @returns iprt status code.
714 * @retval VERR_INVALID_PARAMETER on invalid flags.
715 * @retval VERR_NO_MEMORY if out of memory for the semaphore structure and
718 * @param phSpinMtx Where to return the handle to the create semaphore.
719 * @param fFlags Flags, see RTSEMSPINMUTEX_FLAGS_XXX.
721 RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx
, uint32_t fFlags
);
723 /** @name RTSemSpinMutexCreate flags.
725 /** Always take the semaphore in a IRQ safe way.
726 * (In plain words: always disable interrupts.) */
727 #define RTSEMSPINMUTEX_FLAGS_IRQ_SAFE RT_BIT_32(0)
728 /** Mask of valid flags. */
729 #define RTSEMSPINMUTEX_FLAGS_VALID_MASK UINT32_C(0x00000001)
733 * Destroys a spinning mutex semaphore.
735 * @returns iprt status code.
736 * @retval VERR_INVALID_HANDLE (or crash) if the handle is invalid. (NIL will
737 * not cause this status.)
739 * @param hSpinMtx The semaphore handle. NIL_RTSEMSPINMUTEX is ignored
740 * quietly (VINF_SUCCESS).
742 RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx
);
745 * Request the spinning mutex semaphore.
747 * This may block if the context we're called in allows this. If not it will
748 * spin. If called in an interrupt context, we will only spin if the current
749 * owner isn't interrupted. Also, on some systems it is not always possible to
750 * wake up blocking threads in all contexts, so, which will either be indicated
751 * by returning VERR_SEM_BAD_CONTEXT or by temporarily switching the semaphore
752 * into pure spinlock state.
754 * Preemption will be disabled upon return. IRQs may also be disabled.
756 * @returns iprt status code.
757 * @retval VERR_SEM_BAD_CONTEXT if the context it's called in isn't suitable
758 * for releasing it if someone is sleeping on it.
759 * @retval VERR_SEM_DESTROYED if destroyed.
760 * @retval VERR_SEM_NESTED if held by the caller. Asserted.
761 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted
763 * @param hSpinMtx The semaphore handle.
765 RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx
);
768 * Like RTSemSpinMutexRequest but it won't block or spin if the semaphore is
769 * held by someone else.
771 * @returns iprt status code.
772 * @retval VERR_SEM_BUSY if held by someone else.
773 * @retval VERR_SEM_DESTROYED if destroyed.
774 * @retval VERR_SEM_NESTED if held by the caller. Asserted.
775 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted
777 * @param hSpinMtx The semaphore handle.
779 RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx
);
782 * Releases the semaphore previously acquired by RTSemSpinMutexRequest or
783 * RTSemSpinMutexTryRequest.
785 * @returns iprt status code.
786 * @retval VERR_SEM_DESTROYED if destroyed.
787 * @retval VERR_NOT_OWNER if not owner. Asserted.
788 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted.
790 * @param hSpinMtx The semaphore handle.
792 RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx
);
797 /** @defgroup grp_rt_sem_rw RTSemRW - Read / Write Semaphores
799 * Read/write semaphores are a fancier version of mutexes in that they grant
800 * read access to the protected data to several threads at the same time but
801 * allow only one writer at a time. This can make code scale better at the
802 * expense of slightly more overhead in mutex management.
807 * Creates a read/write semaphore.
809 * @returns iprt status code.
810 * @param phRWSem Where to store the handle to the newly created
813 RTDECL(int) RTSemRWCreate(PRTSEMRW phRWSem
);
816 * Creates a read/write semaphore.
818 * @returns iprt status code.
819 * @param phRWSem Where to store the handle to the newly created
821 * @param fFlags Flags, any combination of the RTSEMRW_FLAGS_XXX
823 * @param hClass The class (no reference consumed). If NIL, no
824 * lock order validation will be performed on this
826 * @param uSubClass The sub-class. This is used to define lock
827 * order within a class. RTLOCKVAL_SUB_CLASS_NONE
828 * is the recommended value here.
829 * @param pszNameFmt Name format string for the lock validator,
830 * optional (NULL). Max length is 32 bytes.
831 * @param ... Format string arguments.
833 RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem
, uint32_t fFlags
, RTLOCKVALCLASS hClass
, uint32_t uSubClass
,
834 const char *pszNameFmt
, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
836 /** @name RTSemRWCreateEx flags
838 /** Disables lock validation. */
839 #define RTSEMRW_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
843 * Destroys a read/write semaphore.
845 * @returns iprt status code.
846 * @param hRWSem Handle to the read/write semaphore. NIL is
847 * quietly ignored (VINF_SUCCESS).
849 RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem
);
852 * Changes the lock validator sub-class of the read/write semaphore.
854 * It is recommended to try make sure that nobody is using this semaphore while
855 * changing the value.
857 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
858 * lock validator isn't compiled in or either of the parameters are
860 * @param hRWSem Handle to the read/write semaphore.
861 * @param uSubClass The new sub-class value.
863 RTDECL(uint32_t) RTSemRWSetSubClass(RTSEMRW hRWSem
, uint32_t uSubClass
);
866 * Request read access to a read/write semaphore, resume on interruption
868 * @returns iprt status code.
869 * @retval VINF_SUCCESS on success.
870 * @retval VERR_INTERRUPT if the wait was interrupted.
871 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
873 * @param hRWSem Handle to the read/write semaphore.
874 * @param cMillies The number of milliseconds to wait.
876 RTDECL(int) RTSemRWRequestRead(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
);
879 * Request read access to a read/write semaphore, return on interruption
881 * @returns iprt status code.
882 * @retval VINF_SUCCESS on success.
883 * @retval VERR_INTERRUPT if the wait was interrupted.
884 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
886 * @param hRWSem Handle to the read/write semaphore.
887 * @param cMillies The number of milliseconds to wait.
889 RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
);
892 * Debug version of RTSemRWRequestRead that tracks the location.
894 * @returns iprt status code.
895 * @retval VINF_SUCCESS on success.
896 * @retval VERR_INTERRUPT if the wait was interrupted.
897 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
899 * @param hRWSem Handle to the read/write semaphore.
900 * @param cMillies The number of milliseconds to wait.
901 * @param uId Some kind of locking location ID. Typically a
902 * return address up the stack. Optional (0).
903 * @param SRC_POS The source position where call is being made
904 * from. Use RT_SRC_POS when possible. Optional.
906 RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
, RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
909 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
911 * @returns iprt status code.
912 * @retval VINF_SUCCESS on success.
913 * @retval VERR_INTERRUPT if the wait was interrupted.
914 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
916 * @param hRWSem Handle to the read/write semaphore.
917 * @param cMillies The number of milliseconds to wait.
918 * @param uId Some kind of locking location ID. Typically a
919 * return address up the stack. Optional (0).
920 * @param SRC_POS The source position where call is being made
921 * from. Use RT_SRC_POS when possible. Optional.
923 RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
, RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
926 * Request read access to a read/write semaphore, extended edition.
928 * @returns iprt status code.
929 * @retval VINF_SUCCESS on success.
930 * @retval VERR_INTERRUPT if the wait was interrupted.
931 * @retval VERR_TIMEOUT if the wait timed out.
932 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
934 * @param hRWSem Handle to the read/write semaphore.
935 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
936 * @param uTimeout The timeout, ignored if
937 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
938 * Whether this is absolute or relative,
939 * milliseconds or nanoseconds depends on the @a
940 * fFlags value. Do not pass RT_INDEFINITE_WAIT
941 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
943 RTDECL(int) RTSemRWRequestReadEx(RTSEMRW hRWSem
, uint32_t fFlags
, uint64_t uTimeout
);
947 * Debug version of RTSemRWRequestReadEx that tracks the location.
949 * @returns iprt status code.
950 * @retval VINF_SUCCESS on success.
951 * @retval VERR_INTERRUPT if the wait was interrupted.
952 * @retval VERR_TIMEOUT if the wait timed out.
953 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
955 * @param hRWSem Handle to the read/write semaphore.
956 * @param fFlags See RTSemRWRequestReadEx.
957 * @param uTimeout See RTSemRWRequestReadEx.
958 * @param uId Some kind of locking location ID. Typically a
959 * return address up the stack. Optional (0).
960 * @param SRC_POS The source position where call is being made
961 * from. Use RT_SRC_POS when possible. Optional.
963 RTDECL(int) RTSemRWRequestReadExDebug(RTSEMRW hRWSem
, uint32_t fFlags
, uint64_t uTimeout
,
964 RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
967 * Release read access to a read/write semaphore.
969 * @returns iprt status code.
970 * @param hRWSem Handle to the read/write semaphore. It goes
971 * without saying that caller must own read
972 * privileges to the semaphore.
974 RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem
);
977 * Request write access to a read/write semaphore, resume on interruption.
979 * @returns iprt status code.
980 * @retval VINF_SUCCESS on success.
981 * @retval VERR_DEADLOCK if the caller owned the read lock.
982 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
984 * @param hRWSem Handle to the read/write semaphore.
985 * @param cMillies The number of milliseconds to wait.
987 RTDECL(int) RTSemRWRequestWrite(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
);
990 * Request write access to a read/write semaphore, return on interruption.
992 * @returns iprt status code.
993 * @retval VINF_SUCCESS on success.
994 * @retval VERR_INTERRUPT if the wait was interrupted.
995 * @retval VERR_DEADLOCK if the caller owned the read lock.
996 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
998 * @param hRWSem Handle to the read/write semaphore.
999 * @param cMillies The number of milliseconds to wait.
1001 RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
);
1004 * Debug version of RTSemRWRequestWrite that tracks the location.
1006 * @returns IPRT status code, see RTSemRWRequestWrite.
1007 * @param hRWSem Handle to the read/write semaphore.
1008 * @param cMillies The number of milliseconds to wait.
1009 * @param uId Some kind of locking location ID. Typically a
1010 * return address up the stack. Optional (0).
1011 * @param SRC_POS The source position where call is being made
1012 * from. Use RT_SRC_POS when possible. Optional.
1014 RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
, RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
1017 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
1019 * @returns IPRT status code, see RTSemRWRequestWriteNoResume.
1020 * @param hRWSem Handle to the read/write semaphore.
1021 * @param cMillies The number of milliseconds to wait.
1022 * @param uId Some kind of locking location ID. Typically a
1023 * return address up the stack. Optional (0).
1024 * @param SRC_POS The source position where call is being made
1025 * from. Use RT_SRC_POS when possible. Optional.
1027 RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW hRWSem
, RTMSINTERVAL cMillies
, RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
1030 * Request write access to a read/write semaphore, extended edition.
1032 * @returns iprt status code.
1033 * @retval VINF_SUCCESS on success.
1034 * @retval VERR_INTERRUPTED if the wait was interrupted.
1035 * @retval VERR_TIMEOUT if the wait timed out.
1036 * @retval VERR_DEADLOCK if the caller owned the read lock. Do not depend on
1037 * this as it is implementation specific.
1038 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
1040 * @param hRWSem Handle to the read/write semaphore.
1041 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
1042 * @param uTimeout The timeout, ignored if
1043 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
1044 * Whether this is absolute or relative,
1045 * milliseconds or nanoseconds depends on the @a
1046 * fFlags value. Do not pass RT_INDEFINITE_WAIT
1047 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
1049 RTDECL(int) RTSemRWRequestWriteEx(RTSEMRW hRWSem
, uint32_t fFlags
, uint64_t uTimeout
);
1052 * Debug version of RTSemRWRequestWriteEx that tracks the location.
1054 * @returns IPRT status code, see RTSemRWRequestWriteEx.
1055 * @param hRWSem Handle to the read/write semaphore.
1056 * @param fFlags See RTSemRWRequestWriteEx.
1057 * @param uTimeout See RTSemRWRequestWriteEx.
1058 * @param uId Some kind of locking location ID. Typically a
1059 * return address up the stack. Optional (0).
1060 * @param SRC_POS The source position where call is being made
1061 * from. Use RT_SRC_POS when possible. Optional.
1063 RTDECL(int) RTSemRWRequestWriteExDebug(RTSEMRW hRWSem
, uint32_t fFlags
, uint64_t uTimeout
,
1064 RTHCUINTPTR uId
, RT_SRC_POS_DECL
);
1067 * Release write access to a read/write semaphore.
1069 * @returns iprt status code.
1070 * @param hRWSem Handle to the read/write semaphore. Goes
1071 * without saying that caller must have write
1072 * access to the semaphore.
1074 RTDECL(int) RTSemRWReleaseWrite(RTSEMRW hRWSem
);
1077 * Checks if the caller is the exclusive semaphore owner.
1079 * @returns true / false accoringly.
1080 * @param hRWSem Handle to the read/write semaphore.
1082 RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW hRWSem
);
1085 * Checks if the caller is one of the read owners of the semaphore.
1087 * @note !CAUTION! This API doesn't work reliably if lock validation isn't
1088 * enabled. Meaning, the answer is not trustworhty unless
1089 * RT_LOCK_STRICT or RTSEMRW_STRICT was defined at build time. Also,
1090 * make sure you do not use RTSEMRW_FLAGS_NO_LOCK_VAL when creating
1091 * the semaphore. And finally, if you used a locking class, don't
1092 * disable deadlock detection by setting cMsMinDeadlock to
1093 * RT_INDEFINITE_WAIT.
1095 * In short, only use this for assertions.
1097 * @returns true if reader, false if not.
1098 * @param hRWSem Handle to the read/write semaphore.
1099 * @param fWannaHear What you'd like to hear when lock validation is
1100 * not available. (For avoiding asserting all over
1103 RTDECL(bool) RTSemRWIsReadOwner(RTSEMRW hRWSem
, bool fWannaHear
);
1106 * Gets the write recursion count.
1108 * @returns The write recursion count (0 if bad semaphore handle).
1109 * @param hRWSem Handle to the read/write semaphore.
1111 RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem
);
1114 * Gets the read recursion count of the current writer.
1116 * @returns The read recursion count (0 if bad semaphore handle).
1117 * @param hRWSem Handle to the read/write semaphore.
1119 RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem
);
1122 * Gets the current number of reads.
1124 * This includes all read recursions, so it might be higher than the number of
1125 * read owners. It does not include reads done by the current writer.
1127 * @returns The read count (0 if bad semaphore handle).
1128 * @param hRWSem Handle to the read/write semaphore.
1130 RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem
);
1132 /* Strict build: Remap the four request calls to the debug versions. */
1133 #if defined(RT_STRICT) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
1134 # ifdef ___iprt_asm_h
1135 # define RTSemRWRequestRead(hRWSem, cMillies) RTSemRWRequestReadDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1136 # define RTSemRWRequestReadNoResume(hRWSem, cMillies) RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1137 # define RTSemRWRequestWrite(hRWSem, cMillies) RTSemRWRequestWriteDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1138 # define RTSemRWRequestWriteNoResume(hRWSem, cMillies) RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1139 # define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout) RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1141 # define RTSemRWRequestRead(hRWSem, cMillies) RTSemRWRequestReadDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1142 # define RTSemRWRequestReadNoResume(hRWSem, cMillies) RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1143 # define RTSemRWRequestWrite(hRWSem, cMillies) RTSemRWRequestWriteDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1144 # define RTSemRWRequestWriteNoResume(hRWSem, cMillies) RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1145 # define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout) RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), 0, RT_SRC_POS)
1149 /* Strict lock order: Automatically classify locks by init location. */
1150 #if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
1151 # define RTSemRWCreate(phSemRW) \
1152 RTSemRWCreateEx((phSemRW), 0 /*fFlags*/, \
1153 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
1154 RTLOCKVAL_SUB_CLASS_NONE, NULL)
1160 /** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct
1162 * Serialization of a two way communication.
1169 typedef enum RTPINGPONGSPEAKER
1171 /** Not initialized. */
1172 RTPINGPONGSPEAKER_UNINITIALIZE
= 0,
1173 /** Ping is speaking, Pong is waiting. */
1174 RTPINGPONGSPEAKER_PING
,
1175 /** Pong is signaled, Ping is waiting. */
1176 RTPINGPONGSPEAKER_PONG_SIGNALED
,
1177 /** Pong is speaking, Ping is waiting. */
1178 RTPINGPONGSPEAKER_PONG
,
1179 /** Ping is signaled, Pong is waiting. */
1180 RTPINGPONGSPEAKER_PING_SIGNALED
,
1181 /** Hack to ensure that it's at least 32-bits wide. */
1182 RTPINGPONGSPEAKER_HACK
= 0x7fffffff
1183 } RTPINGPONGSPEAKER
;
1186 * Ping-Pong construct.
1188 * Two threads, one saying Ping and the other saying Pong. The construct
1189 * makes sure they don't speak out of turn and that they can wait and poll
1190 * on the conversation.
1192 typedef struct RTPINGPONG
1194 /** The semaphore the Ping thread waits on. */
1196 /** The semaphore the Pong thread waits on. */
1198 /** The current speaker. */
1199 volatile RTPINGPONGSPEAKER enmSpeaker
;
1200 #if HC_ARCH_BITS == 64
1201 /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
1202 uint32_t u32Padding
;
1205 /** Pointer to Ping-Pong construct. */
1206 typedef RTPINGPONG
*PRTPINGPONG
;
1209 * Init a Ping-Pong construct.
1211 * @returns iprt status code.
1212 * @param pPP Pointer to the ping-pong structure which needs initialization.
1214 RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP
);
1217 * Deletes a Ping-Pong construct.
1219 * @returns iprt status code.
1220 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
1221 * (I.e. put into uninitialized state.)
1223 RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP
);
1226 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
1227 * This is called by the ping thread.
1229 * @returns iprt status code.
1230 * @param pPP Pointer to the ping-pong structure to ping.
1232 RTDECL(int) RTSemPing(PRTPINGPONG pPP
);
1235 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
1236 * This is called by the pong thread.
1238 * @returns iprt status code.
1239 * @param pPP Pointer to the ping-pong structure to pong.
1241 RTDECL(int) RTSemPong(PRTPINGPONG pPP
);
1244 * Wait function for the ping thread.
1246 * @returns iprt status code.
1247 * Will not return VERR_INTERRUPTED.
1248 * @param pPP Pointer to the ping-pong structure to wait on.
1249 * @param cMillies Number of milliseconds to wait.
1251 RTDECL(int) RTSemPingWait(PRTPINGPONG pPP
, RTMSINTERVAL cMillies
);
1254 * Wait function for the pong thread.
1256 * @returns iprt status code.
1257 * Will not return VERR_INTERRUPTED.
1258 * @param pPP Pointer to the ping-pong structure to wait on.
1259 * @param cMillies Number of milliseconds to wait.
1261 RTDECL(int) RTSemPongWait(PRTPINGPONG pPP
, RTMSINTERVAL cMillies
);
1265 * Checks if the pong thread is speaking.
1267 * @returns true / false.
1268 * @param pPP Pointer to the ping-pong structure.
1269 * @remark This is NOT the same as !RTSemPongIsSpeaker().
1271 DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP
)
1273 RTPINGPONGSPEAKER enmSpeaker
= pPP
->enmSpeaker
;
1274 return enmSpeaker
== RTPINGPONGSPEAKER_PING
;
1279 * Checks if the pong thread is speaking.
1281 * @returns true / false.
1282 * @param pPP Pointer to the ping-pong structure.
1283 * @remark This is NOT the same as !RTSemPingIsSpeaker().
1285 DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP
)
1287 RTPINGPONGSPEAKER enmSpeaker
= pPP
->enmSpeaker
;
1288 return enmSpeaker
== RTPINGPONGSPEAKER_PONG
;
1293 * Checks whether the ping thread should wait.
1295 * @returns true / false.
1296 * @param pPP Pointer to the ping-pong structure.
1297 * @remark This is NOT the same as !RTSemPongShouldWait().
1299 DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP
)
1301 RTPINGPONGSPEAKER enmSpeaker
= pPP
->enmSpeaker
;
1302 return enmSpeaker
== RTPINGPONGSPEAKER_PONG
1303 || enmSpeaker
== RTPINGPONGSPEAKER_PONG_SIGNALED
1304 || enmSpeaker
== RTPINGPONGSPEAKER_PING_SIGNALED
;
1309 * Checks whether the pong thread should wait.
1311 * @returns true / false.
1312 * @param pPP Pointer to the ping-pong structure.
1313 * @remark This is NOT the same as !RTSemPingShouldWait().
1315 DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP
)
1317 RTPINGPONGSPEAKER enmSpeaker
= pPP
->enmSpeaker
;
1318 return enmSpeaker
== RTPINGPONGSPEAKER_PING
1319 || enmSpeaker
== RTPINGPONGSPEAKER_PING_SIGNALED
1320 || enmSpeaker
== RTPINGPONGSPEAKER_PONG_SIGNALED
;
1326 /** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads
1328 * The crossroads semaphore is intended to prevent two classes of incompatible
1329 * events from occurring simultaneously, like south/north bound traffic and
1330 * west/east bound traffic at a 4-way junction.
1332 * @remarks In order to simplify the implementation, the current flow is always
1333 * given priority. So, it won't work at all well when busy!
1335 * @remarks "XRoads" is used as a name because it is briefer than "crossroads"
1336 * and it slightly stresses that is a 4 way crossing to the users of
1342 * Creates a crossroads semaphore.
1344 * @returns IPRT status code.
1346 * @param phXRoads Where to return the handle to the newly created
1347 * crossroads semaphore.
1349 RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads
);
1352 * Destroys a crossroads semaphore.
1354 * @returns IPRT status code.
1356 * @param hXRoads Handle to the crossroads semaphore that is to be
1357 * destroyed. NIL_RTSEMXROADS is quitetly ignored
1360 RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads
);
1363 * Enter the crossroads from the south or north.
1365 * (Coupled with RTSemXRoadsNSLeave.)
1367 * @returns IPRT status code.
1368 * @param hXRoads Handle to the crossroads semaphore.
1370 RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads
);
1373 * Leave the crossroads to the north or south.
1375 * (Coupled with RTSemXRoadsNSEnter.)
1377 * @returns IPRT status code.
1378 * @param hXRoads Handle to the crossroads semaphore.
1380 RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads
);
1383 * Leave the crossroads from the east or west.
1385 * (Coupled with RTSemXRoadsEWLeave.)
1387 * @returns IPRT status code.
1388 * @param hXRoads Handle to the crossroads semaphore.
1390 RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads
);
1393 * Leave the crossroads to the west or east.
1395 * (Coupled with RTSemXRoadsEWEnter.)
1397 * @returns IPRT status code.
1398 * @param hXRoads Handle to the crossroads semaphore.
1400 RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads
);