]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - ubuntu/vbox/include/iprt/semaphore.h
UBUNTU: SAUCE: update vbox
[mirror_ubuntu-artful-kernel.git] / ubuntu / vbox / include / iprt / semaphore.h
1 /** @file
2 * IPRT - Semaphore.
3 */
4
5 /*
6 * Copyright (C) 2006-2016 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_semaphore_h
27 #define ___iprt_semaphore_h
28
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>
33 #endif
34
35
36 RT_C_DECLS_BEGIN
37
38 /** @defgroup grp_rt_sems RTSem - Semaphores
39 *
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
43 * interesting.
44 *
45 * @ingroup grp_rt
46 * @{
47 */
48
49
50 /** @name Generic Semaphore Wait Flags.
51 *
52 * @remarks Exactly one of RTSEMWAIT_FLAGS_RELATIVE and
53 * RTSEMWAIT_FLAGS_ABSOLUTE must be set, unless
54 * RTSEMWAIT_FLAGS_INDEFINITE is used.
55 *
56 * Exactly one of RTSEMWAIT_FLAGS_NANOSECS and
57 * RTSEMWAIT_FLAGS_MILLISECS must be set, unless
58 * RTSEMWAIT_FLAGS_INDEFINITE is used.
59 *
60 * Exactly one of RTSEMWAIT_FLAGS_RESUME and RTSEMWAIT_FLAGS_NORESUME
61 * must be set.
62 *
63 * The interruptible vs resume stuff is ring-0 vs ring-3 semantics.
64 *
65 * @{ */
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)
74 /** Indefinite wait.
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)
79
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
88
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) ))
95 /** @} */
96
97
98
99 /** @defgroup grp_rt_sems_event RTSemEvent - Single Release Event Semaphores
100 *
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.
105 *
106 * @{ */
107
108 /**
109 * Create an event semaphore.
110 *
111 * @returns iprt status code.
112 * @param phEventSem Where to store the handle to the newly created
113 * event semaphore.
114 */
115 RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem);
116
117 /**
118 * Create an event semaphore.
119 *
120 * @returns iprt status code.
121 * @param phEventSem Where to store the handle to the newly created
122 * event semaphore.
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.
132 */
133 RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
134 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
135
136 /** @name RTSemMutexCreateEx flags
137 * @{ */
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)
142 /** @} */
143
144 /**
145 * Destroy an event semaphore.
146 *
147 * @returns iprt status code.
148 * @param hEventSem Handle of the event semaphore. NIL_RTSEMEVENT
149 * is quietly ignored (VINF_SUCCESS).
150 */
151 RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem);
152
153 /**
154 * Signal an event semaphore.
155 *
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.
159 *
160 * @returns iprt status code.
161 * @param hEventSem The event semaphore to signal.
162 *
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.
166 */
167 RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem);
168
169 /**
170 * Wait for the event semaphore to be signaled, resume on interruption.
171 *
172 * This function will resume if the wait is interrupted by an async system event
173 * (like a unix signal) or similar.
174 *
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.
179 */
180 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
181
182 /**
183 * Wait for the event semaphore to be signaled, return on interruption.
184 *
185 * This function will not resume the wait if interrupted.
186 *
187 * @returns iprt status code.
188 * @param hEventSem The event semaphore to wait on.
189 * @param cMillies Number of milliseconds to wait.
190 */
191 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
192
193 /**
194 * Extended API for waiting on an event semaphore to be signaled.
195 *
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.
205 */
206 RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout);
207
208 /**
209 * Debug version of RTSemEventWaitEx that tracks the location.
210 *
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.
219 */
220 RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
221 RTHCUINTPTR uId, RT_SRC_POS_DECL);
222
223 /**
224 * Gets the best timeout resolution that RTSemEventWaitEx can do.
225 *
226 * @returns The resolution in nanoseconds.
227 */
228 RTDECL(uint32_t) RTSemEventGetResolution(void);
229
230 /**
231 * Sets the signaller thread to one specific thread.
232 *
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
235 * signalling thread.
236 *
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.
241 */
242 RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
243
244 /**
245 * To add more signalling threads.
246 *
247 * First call RTSemEventSetSignaller then add further threads with this.
248 *
249 * @param hEventSem The event semaphore.
250 * @param hThread The thread that will signal it. NIL_RTTHREAD is
251 * not accepted.
252 */
253 RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
254
255 /**
256 * To remove a signalling thread.
257 *
258 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
259 *
260 * @param hEventSem The event semaphore.
261 * @param hThread A previously added thread.
262 */
263 RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
264
265 /** @} */
266
267
268 /** @defgroup grp_rt_sems_event_multi RTSemEventMulti - Multiple Release Event Semaphores
269 *
270 * A variant of @ref grp_rt_sems_event where all threads will be unblocked when
271 * signalling the semaphore.
272 *
273 * @{ */
274
275 /**
276 * Creates a multiple release event semaphore.
277 *
278 * @returns iprt status code.
279 * @param phEventMultiSem Where to store the handle to the newly created
280 * multiple release event semaphore.
281 */
282 RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem);
283
284 /**
285 * Creates a multiple release event semaphore.
286 *
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.
299 */
300 RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
301 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
302
303 /** @name RTSemMutexCreateEx flags
304 * @{ */
305 /** Disables lock validation. */
306 #define RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
307 /** @} */
308
309 /**
310 * Destroy an event multi semaphore.
311 *
312 * @returns iprt status code.
313 * @param hEventMultiSem The multiple release event semaphore. NIL is
314 * quietly ignored (VINF_SUCCESS).
315 */
316 RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem);
317
318 /**
319 * Signal an event multi semaphore.
320 *
321 * @returns iprt status code.
322 * @param hEventMultiSem The multiple release event semaphore.
323 *
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.
327 */
328 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem);
329
330 /**
331 * Resets an event multi semaphore to non-signaled state.
332 *
333 * @returns iprt status code.
334 * @param hEventMultiSem The multiple release event semaphore.
335 */
336 RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem);
337
338 /**
339 * Wait for the event multi semaphore to be signaled, resume on interruption.
340 *
341 * This function will resume if the wait is interrupted by an async
342 * system event (like a unix signal) or similar.
343 *
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.
348 */
349 RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
350
351 /**
352 * Wait for the event multi semaphore to be signaled, return on interruption.
353 *
354 * This function will not resume the wait if interrupted.
355 *
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.
361 */
362 RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
363
364 /**
365 * Extended API for waiting on an event semaphore to be signaled.
366 *
367 * @returns IPRT status code.
368 * @param hEventMultiSem The multiple release event semaphore to wait
369 * on.
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.
377 */
378 RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout);
379
380 /**
381 * Debug version of RTSemEventMultiWaitEx that tracks the location.
382
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.
391 */
392 RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
393 RTHCUINTPTR uId, RT_SRC_POS_DECL);
394
395 /**
396 * Gets the best timeout resolution that RTSemEventMultiWaitEx can do.
397 *
398 * @returns The resolution in nanoseconds.
399 */
400 RTDECL(uint32_t) RTSemEventMultiGetResolution(void);
401
402 /**
403 * Sets the signaller thread to one specific thread.
404 *
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
407 * signalling thread.
408 *
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.
413 */
414 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
415
416 /**
417 * To add more signalling threads.
418 *
419 * First call RTSemEventSetSignaller then add further threads with this.
420 *
421 * @param hEventMultiSem The multiple release event semaphore.
422 * @param hThread The thread that will signal it. NIL_RTTHREAD is
423 * not accepted.
424 */
425 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
426
427 /**
428 * To remove a signalling thread.
429 *
430 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
431 *
432 * @param hEventMultiSem The multiple release event semaphore.
433 * @param hThread A previously added thread.
434 */
435 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
436
437 /** @} */
438
439
440 /** @defgroup grp_rt_sems_mutex RTSemMutex - Mutex semaphores.
441 *
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.
445 *
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 .
449 *
450 * @{ */
451
452 /**
453 * Create a mutex semaphore.
454 *
455 * @returns iprt status code.
456 * @param phMutexSem Where to store the mutex semaphore handle.
457 */
458 RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem);
459
460 /**
461 * Creates a read/write semaphore.
462 *
463 * @returns iprt status code.
464 * @param phMutexSem Where to store the handle to the newly created
465 * mutex semaphore.
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
470 * lock.
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.
477 */
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);
480
481 /** @name RTSemMutexCreateEx flags
482 * @{ */
483 /** Disables lock validation. */
484 #define RTSEMMUTEX_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
485 /** @} */
486
487
488 /**
489 * Destroy a mutex semaphore.
490 *
491 * @returns iprt status code.
492 * @param hMutexSem The mutex semaphore to destroy. NIL is quietly
493 * ignored (VINF_SUCCESS).
494 */
495 RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem);
496
497 /**
498 * Changes the lock validator sub-class of the mutex semaphore.
499 *
500 * It is recommended to try make sure that nobody is using this semaphore while
501 * changing the value.
502 *
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
505 * invalid.
506 * @param hMutexSem The handle to the mutex semaphore.
507 * @param uSubClass The new sub-class value.
508 */
509 RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass);
510
511 /**
512 * Request ownership of a mutex semaphore, resume on interruption.
513 *
514 * This function will resume if the wait is interrupted by an async
515 * system event (like a unix signal) or similar.
516 *
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.
520 *
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.
525 */
526 RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
527
528 /**
529 * Request ownership of a mutex semaphore, return on interruption.
530 *
531 * This function will not resume the wait if interrupted.
532 *
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.
536 *
537 * @returns iprt status code.
538 * @param hMutexSem The mutex semaphore to request ownership over.
539 * @param cMillies The number of milliseconds to wait.
540 */
541 RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
542
543 /**
544 * Debug version of RTSemMutexRequest that tracks the location.
545 *
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.
554 */
555 RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
556
557 /**
558 * Debug version of RTSemMutexRequestNoResume that tracks the location.
559 *
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.
567 */
568 RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
569
570 /**
571 * Request ownership of a mutex semaphore, extended edition.
572 *
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.
576 *
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.
586 */
587 RTDECL(int) RTSemMutexRequestEx(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout);
588
589 /**
590 * Debug version of RTSemMutexRequestEx that tracks the location.
591 *
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.
600 */
601 RTDECL(int) RTSemMutexRequestExDebug(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout,
602 RTHCUINTPTR uId, RT_SRC_POS_DECL);
603
604 /**
605 * Release the ownership of a mutex semaphore.
606 *
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
610 * it.
611 */
612 RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem);
613
614 /**
615 * Checks if the mutex semaphore is owned or not.
616 *
617 * @returns true if owned, false if not.
618 * @param hMutexSem The mutex semaphore.
619 */
620 RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem);
621
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)
628 # else
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)
632 # endif
633 #endif
634
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)
641 #endif
642
643 /** @} */
644
645
646 /** @defgroup grp_rt_sems_fast_mutex RTSemFastMutex - Fast Mutex Semaphores
647 *
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.
652 *
653 * @remarks The fast mutexes has sideeffects on IRQL on Windows hosts. So use
654 * with care and test on windows with driver verifier.
655 *
656 * @{ */
657
658 /**
659 * Create a fast mutex semaphore.
660 *
661 * @returns iprt status code.
662 * @param phFastMtx Where to store the handle to the newly created
663 * fast mutex semaphore.
664 *
665 * @remarks Fast mutex semaphores are not recursive.
666 */
667 RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx);
668
669 /**
670 * Destroy a fast mutex semaphore.
671 *
672 * @returns iprt status code.
673 * @param hFastMtx Handle to the fast mutex semaphore. NIL is
674 * quietly ignored (VINF_SUCCESS).
675 */
676 RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx);
677
678 /**
679 * Request ownership of a fast mutex semaphore.
680 *
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.
684 *
685 * @returns iprt status code.
686 * @param hFastMtx Handle to the fast mutex semaphore.
687 */
688 RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx);
689
690 /**
691 * Release the ownership of a fast mutex semaphore.
692 *
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
696 * it.
697 */
698 RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx);
699
700 /** @} */
701
702
703 /** @defgroup grp_rt_sems_spin_mutex RTSemSpinMutex - Spinning Mutex Semaphores
704 *
705 * A very adaptive variant of mutex semaphore that is tailored for the ring-0
706 * logger.
707 *
708 * @{ */
709
710 /**
711 * Creates a spinning mutex semaphore.
712 *
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
716 * handle.
717 *
718 * @param phSpinMtx Where to return the handle to the create semaphore.
719 * @param fFlags Flags, see RTSEMSPINMUTEX_FLAGS_XXX.
720 */
721 RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags);
722
723 /** @name RTSemSpinMutexCreate flags.
724 * @{ */
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)
730 /** @} */
731
732 /**
733 * Destroys a spinning mutex semaphore.
734 *
735 * @returns iprt status code.
736 * @retval VERR_INVALID_HANDLE (or crash) if the handle is invalid. (NIL will
737 * not cause this status.)
738 *
739 * @param hSpinMtx The semaphore handle. NIL_RTSEMSPINMUTEX is ignored
740 * quietly (VINF_SUCCESS).
741 */
742 RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx);
743
744 /**
745 * Request the spinning mutex semaphore.
746 *
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.
753 *
754 * Preemption will be disabled upon return. IRQs may also be disabled.
755 *
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
762 *
763 * @param hSpinMtx The semaphore handle.
764 */
765 RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx);
766
767 /**
768 * Like RTSemSpinMutexRequest but it won't block or spin if the semaphore is
769 * held by someone else.
770 *
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
776 *
777 * @param hSpinMtx The semaphore handle.
778 */
779 RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx);
780
781 /**
782 * Releases the semaphore previously acquired by RTSemSpinMutexRequest or
783 * RTSemSpinMutexTryRequest.
784 *
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.
789 *
790 * @param hSpinMtx The semaphore handle.
791 */
792 RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx);
793
794 /** @} */
795
796
797 /** @defgroup grp_rt_sem_rw RTSemRW - Read / Write Semaphores
798 *
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.
803 *
804 * @{ */
805
806 /**
807 * Creates a read/write semaphore.
808 *
809 * @returns iprt status code.
810 * @param phRWSem Where to store the handle to the newly created
811 * RW semaphore.
812 */
813 RTDECL(int) RTSemRWCreate(PRTSEMRW phRWSem);
814
815 /**
816 * Creates a read/write semaphore.
817 *
818 * @returns iprt status code.
819 * @param phRWSem Where to store the handle to the newly created
820 * RW semaphore.
821 * @param fFlags Flags, any combination of the RTSEMRW_FLAGS_XXX
822 * \#defines.
823 * @param hClass The class (no reference consumed). If NIL, no
824 * lock order validation will be performed on this
825 * lock.
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.
832 */
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);
835
836 /** @name RTSemRWCreateEx flags
837 * @{ */
838 /** Disables lock validation. */
839 #define RTSEMRW_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
840 /** @} */
841
842 /**
843 * Destroys a read/write semaphore.
844 *
845 * @returns iprt status code.
846 * @param hRWSem Handle to the read/write semaphore. NIL is
847 * quietly ignored (VINF_SUCCESS).
848 */
849 RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem);
850
851 /**
852 * Changes the lock validator sub-class of the read/write semaphore.
853 *
854 * It is recommended to try make sure that nobody is using this semaphore while
855 * changing the value.
856 *
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
859 * invalid.
860 * @param hRWSem Handle to the read/write semaphore.
861 * @param uSubClass The new sub-class value.
862 */
863 RTDECL(uint32_t) RTSemRWSetSubClass(RTSEMRW hRWSem, uint32_t uSubClass);
864
865 /**
866 * Request read access to a read/write semaphore, resume on interruption
867 *
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.
872 *
873 * @param hRWSem Handle to the read/write semaphore.
874 * @param cMillies The number of milliseconds to wait.
875 */
876 RTDECL(int) RTSemRWRequestRead(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
877
878 /**
879 * Request read access to a read/write semaphore, return on interruption
880 *
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.
885 *
886 * @param hRWSem Handle to the read/write semaphore.
887 * @param cMillies The number of milliseconds to wait.
888 */
889 RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
890
891 /**
892 * Debug version of RTSemRWRequestRead that tracks the location.
893 *
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.
898 *
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.
905 */
906 RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
907
908 /**
909 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
910 *
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.
915 *
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.
922 */
923 RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
924
925 /**
926 * Request read access to a read/write semaphore, extended edition.
927 *
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.
933 *
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.
942 */
943 RTDECL(int) RTSemRWRequestReadEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout);
944
945
946 /**
947 * Debug version of RTSemRWRequestReadEx that tracks the location.
948 *
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.
954 *
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.
962 */
963 RTDECL(int) RTSemRWRequestReadExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout,
964 RTHCUINTPTR uId, RT_SRC_POS_DECL);
965
966 /**
967 * Release read access to a read/write semaphore.
968 *
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.
973 */
974 RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem);
975
976 /**
977 * Request write access to a read/write semaphore, resume on interruption.
978 *
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.
983 *
984 * @param hRWSem Handle to the read/write semaphore.
985 * @param cMillies The number of milliseconds to wait.
986 */
987 RTDECL(int) RTSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
988
989 /**
990 * Request write access to a read/write semaphore, return on interruption.
991 *
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.
997 *
998 * @param hRWSem Handle to the read/write semaphore.
999 * @param cMillies The number of milliseconds to wait.
1000 */
1001 RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
1002
1003 /**
1004 * Debug version of RTSemRWRequestWrite that tracks the location.
1005 *
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.
1013 */
1014 RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
1015
1016 /**
1017 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
1018 *
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.
1026 */
1027 RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
1028
1029 /**
1030 * Request write access to a read/write semaphore, extended edition.
1031 *
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.
1039 *
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.
1048 */
1049 RTDECL(int) RTSemRWRequestWriteEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout);
1050
1051 /**
1052 * Debug version of RTSemRWRequestWriteEx that tracks the location.
1053 *
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.
1062 */
1063 RTDECL(int) RTSemRWRequestWriteExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout,
1064 RTHCUINTPTR uId, RT_SRC_POS_DECL);
1065
1066 /**
1067 * Release write access to a read/write semaphore.
1068 *
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.
1073 */
1074 RTDECL(int) RTSemRWReleaseWrite(RTSEMRW hRWSem);
1075
1076 /**
1077 * Checks if the caller is the exclusive semaphore owner.
1078 *
1079 * @returns true / false accoringly.
1080 * @param hRWSem Handle to the read/write semaphore.
1081 */
1082 RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW hRWSem);
1083
1084 /**
1085 * Checks if the caller is one of the read owners of the semaphore.
1086 *
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.
1094 *
1095 * In short, only use this for assertions.
1096 *
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
1101 * the place.)
1102 */
1103 RTDECL(bool) RTSemRWIsReadOwner(RTSEMRW hRWSem, bool fWannaHear);
1104
1105 /**
1106 * Gets the write recursion count.
1107 *
1108 * @returns The write recursion count (0 if bad semaphore handle).
1109 * @param hRWSem Handle to the read/write semaphore.
1110 */
1111 RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem);
1112
1113 /**
1114 * Gets the read recursion count of the current writer.
1115 *
1116 * @returns The read recursion count (0 if bad semaphore handle).
1117 * @param hRWSem Handle to the read/write semaphore.
1118 */
1119 RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem);
1120
1121 /**
1122 * Gets the current number of reads.
1123 *
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.
1126 *
1127 * @returns The read count (0 if bad semaphore handle).
1128 * @param hRWSem Handle to the read/write semaphore.
1129 */
1130 RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem);
1131
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)
1140 # else
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)
1146 # endif
1147 #endif
1148
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)
1155 #endif
1156
1157 /** @} */
1158
1159
1160 /** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct
1161 *
1162 * Serialization of a two way communication.
1163 *
1164 * @{ */
1165
1166 /**
1167 * Ping-pong speaker
1168 */
1169 typedef enum RTPINGPONGSPEAKER
1170 {
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;
1184
1185 /**
1186 * Ping-Pong construct.
1187 *
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.
1191 */
1192 typedef struct RTPINGPONG
1193 {
1194 /** The semaphore the Ping thread waits on. */
1195 RTSEMEVENT Ping;
1196 /** The semaphore the Pong thread waits on. */
1197 RTSEMEVENT Pong;
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;
1203 #endif
1204 } RTPINGPONG;
1205 /** Pointer to Ping-Pong construct. */
1206 typedef RTPINGPONG *PRTPINGPONG;
1207
1208 /**
1209 * Init a Ping-Pong construct.
1210 *
1211 * @returns iprt status code.
1212 * @param pPP Pointer to the ping-pong structure which needs initialization.
1213 */
1214 RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
1215
1216 /**
1217 * Deletes a Ping-Pong construct.
1218 *
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.)
1222 */
1223 RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
1224
1225 /**
1226 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
1227 * This is called by the ping thread.
1228 *
1229 * @returns iprt status code.
1230 * @param pPP Pointer to the ping-pong structure to ping.
1231 */
1232 RTDECL(int) RTSemPing(PRTPINGPONG pPP);
1233
1234 /**
1235 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
1236 * This is called by the pong thread.
1237 *
1238 * @returns iprt status code.
1239 * @param pPP Pointer to the ping-pong structure to pong.
1240 */
1241 RTDECL(int) RTSemPong(PRTPINGPONG pPP);
1242
1243 /**
1244 * Wait function for the ping thread.
1245 *
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.
1250 */
1251 RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
1252
1253 /**
1254 * Wait function for the pong thread.
1255 *
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.
1260 */
1261 RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
1262
1263
1264 /**
1265 * Checks if the pong thread is speaking.
1266 *
1267 * @returns true / false.
1268 * @param pPP Pointer to the ping-pong structure.
1269 * @remark This is NOT the same as !RTSemPongIsSpeaker().
1270 */
1271 DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
1272 {
1273 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1274 return enmSpeaker == RTPINGPONGSPEAKER_PING;
1275 }
1276
1277
1278 /**
1279 * Checks if the pong thread is speaking.
1280 *
1281 * @returns true / false.
1282 * @param pPP Pointer to the ping-pong structure.
1283 * @remark This is NOT the same as !RTSemPingIsSpeaker().
1284 */
1285 DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
1286 {
1287 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1288 return enmSpeaker == RTPINGPONGSPEAKER_PONG;
1289 }
1290
1291
1292 /**
1293 * Checks whether the ping thread should wait.
1294 *
1295 * @returns true / false.
1296 * @param pPP Pointer to the ping-pong structure.
1297 * @remark This is NOT the same as !RTSemPongShouldWait().
1298 */
1299 DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
1300 {
1301 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1302 return enmSpeaker == RTPINGPONGSPEAKER_PONG
1303 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
1304 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
1305 }
1306
1307
1308 /**
1309 * Checks whether the pong thread should wait.
1310 *
1311 * @returns true / false.
1312 * @param pPP Pointer to the ping-pong structure.
1313 * @remark This is NOT the same as !RTSemPingShouldWait().
1314 */
1315 DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
1316 {
1317 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1318 return enmSpeaker == RTPINGPONGSPEAKER_PING
1319 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
1320 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
1321 }
1322
1323 /** @} */
1324
1325
1326 /** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads
1327 *
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.
1331 *
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!
1334 *
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
1337 * American English.
1338 * @{
1339 */
1340
1341 /**
1342 * Creates a crossroads semaphore.
1343 *
1344 * @returns IPRT status code.
1345 *
1346 * @param phXRoads Where to return the handle to the newly created
1347 * crossroads semaphore.
1348 */
1349 RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads);
1350
1351 /**
1352 * Destroys a crossroads semaphore.
1353 *
1354 * @returns IPRT status code.
1355 *
1356 * @param hXRoads Handle to the crossroads semaphore that is to be
1357 * destroyed. NIL_RTSEMXROADS is quitetly ignored
1358 * (VINF_SUCCESS).
1359 */
1360 RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads);
1361
1362 /**
1363 * Enter the crossroads from the south or north.
1364 *
1365 * (Coupled with RTSemXRoadsNSLeave.)
1366 *
1367 * @returns IPRT status code.
1368 * @param hXRoads Handle to the crossroads semaphore.
1369 */
1370 RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads);
1371
1372 /**
1373 * Leave the crossroads to the north or south.
1374 *
1375 * (Coupled with RTSemXRoadsNSEnter.)
1376 *
1377 * @returns IPRT status code.
1378 * @param hXRoads Handle to the crossroads semaphore.
1379 */
1380 RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads);
1381
1382 /**
1383 * Leave the crossroads from the east or west.
1384 *
1385 * (Coupled with RTSemXRoadsEWLeave.)
1386 *
1387 * @returns IPRT status code.
1388 * @param hXRoads Handle to the crossroads semaphore.
1389 */
1390 RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads);
1391
1392 /**
1393 * Leave the crossroads to the west or east.
1394 *
1395 * (Coupled with RTSemXRoadsEWEnter.)
1396 *
1397 * @returns IPRT status code.
1398 * @param hXRoads Handle to the crossroads semaphore.
1399 */
1400 RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads);
1401
1402 /** @} */
1403
1404 /** @} */
1405
1406 RT_C_DECLS_END
1407
1408 #endif
1409