VirtualBox

source: vbox/trunk/include/iprt/semaphore.h@ 75704

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

IPRT/r0drv/darwin: RTSemEventSignal and RTSemEventMultiSignal seems to work fine with interrupts disabled and/or from interrupt context. bugref:4686

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.4 KB
Line 
1/** @file
2 * IPRT - Semaphore.
3 */
4
5/*
6 * Copyright (C) 2006-2017 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
36RT_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 */
115RTDECL(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 */
133RTDECL(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 */
151RTDECL(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 * ring-0/Darwin: This works when interrupts are disabled and thereby
168 * in interrupt context, except it cannot race semaphore destruction as
169 * the allocator does not work under these circumstances.
170 */
171RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem);
172
173/**
174 * Wait for the event semaphore to be signaled, resume on interruption.
175 *
176 * This function will resume if the wait is interrupted by an async system event
177 * (like a unix signal) or similar.
178 *
179 * @returns iprt status code.
180 * Will not return VERR_INTERRUPTED.
181 * @param hEventSem The event semaphore to wait on.
182 * @param cMillies Number of milliseconds to wait.
183 */
184RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
185
186/**
187 * Wait for the event semaphore to be signaled, return on interruption.
188 *
189 * This function will not resume the wait if interrupted.
190 *
191 * @returns iprt status code.
192 * @param hEventSem The event semaphore to wait on.
193 * @param cMillies Number of milliseconds to wait.
194 */
195RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
196
197/**
198 * Extended API for waiting on an event semaphore to be signaled.
199 *
200 * @returns IPRT status code.
201 * @param hEventSem The event semaphore to wait on.
202 * @param fFlags Combination of RTSEMWAIT_FLAGS_XXX.
203 * @param uTimeout The timeout, ignored if
204 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
205 * Whether this is absolute or relative,
206 * milliseconds or nanoseconds depends on the @a
207 * fFlags value. Do not pass RT_INDEFINITE_WAIT
208 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
209 */
210RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout);
211
212/**
213 * Debug version of RTSemEventWaitEx that tracks the location.
214 *
215 * @returns IPRT status code, see RTSemEventWaitEx.
216 * @param hEventSem The event semaphore to wait on.
217 * @param fFlags See RTSemEventWaitEx.
218 * @param uTimeout See RTSemEventWaitEx.
219 * @param uId Some kind of locking location ID. Typically a
220 * return address up the stack. Optional (0).
221 * @param SRC_POS The source position where call is being made
222 * from. Use RT_SRC_POS when possible. Optional.
223 */
224RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
225 RTHCUINTPTR uId, RT_SRC_POS_DECL);
226
227/**
228 * Gets the best timeout resolution that RTSemEventWaitEx can do.
229 *
230 * @returns The resolution in nanoseconds.
231 */
232RTDECL(uint32_t) RTSemEventGetResolution(void);
233
234/**
235 * Sets the signaller thread to one specific thread.
236 *
237 * This is only used for validating usage and deadlock detection. When used
238 * after calls to RTSemEventAddSignaller, the specified thread will be the only
239 * signalling thread.
240 *
241 * @param hEventSem The event semaphore.
242 * @param hThread The thread that will signal it. Pass
243 * NIL_RTTHREAD to indicate that there is no
244 * special signalling thread.
245 */
246RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
247
248/**
249 * To add more signalling threads.
250 *
251 * First call RTSemEventSetSignaller then add further threads with this.
252 *
253 * @param hEventSem The event semaphore.
254 * @param hThread The thread that will signal it. NIL_RTTHREAD is
255 * not accepted.
256 */
257RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
258
259/**
260 * To remove a signalling thread.
261 *
262 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
263 *
264 * @param hEventSem The event semaphore.
265 * @param hThread A previously added thread.
266 */
267RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
268
269/** @} */
270
271
272/** @defgroup grp_rt_sems_event_multi RTSemEventMulti - Multiple Release Event Semaphores
273 *
274 * A variant of @ref grp_rt_sems_event where all threads will be unblocked when
275 * signalling the semaphore.
276 *
277 * @{ */
278
279/**
280 * Creates a multiple release event semaphore.
281 *
282 * @returns iprt status code.
283 * @param phEventMultiSem Where to store the handle to the newly created
284 * multiple release event semaphore.
285 */
286RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem);
287
288/**
289 * Creates a multiple release event semaphore.
290 *
291 * @returns iprt status code.
292 * @param phEventMultiSem Where to store the handle to the newly created
293 * multiple release event semaphore.
294 * @param fFlags Flags, any combination of the
295 * RTSEMEVENTMULTI_FLAGS_XXX \#defines.
296 * @param hClass The class (no reference consumed). Since we
297 * don't do order checks on event semaphores, the
298 * use of the class is limited to controlling the
299 * timeout threshold for deadlock detection.
300 * @param pszNameFmt Name format string for the lock validator,
301 * optional (NULL). Max length is 32 bytes.
302 * @param ... Format string arguments.
303 */
304RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
305 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(4, 5);
306
307/** @name RTSemMutexCreateEx flags
308 * @{ */
309/** Disables lock validation. */
310#define RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
311/** @} */
312
313/**
314 * Destroy an event multi semaphore.
315 *
316 * @returns iprt status code.
317 * @param hEventMultiSem The multiple release event semaphore. NIL is
318 * quietly ignored (VINF_SUCCESS).
319 */
320RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem);
321
322/**
323 * Signal an event multi semaphore.
324 *
325 * @returns iprt status code.
326 * @param hEventMultiSem The multiple release event semaphore.
327 *
328 * @remarks ring-0: This works when preemption is disabled. However it is
329 * system specific whether it works in interrupt context or with
330 * interrupts disabled.
331 *
332 * ring-0/Darwin: This works when interrupts are disabled and thereby
333 * in interrupt context, except it cannot race semaphore destruction as
334 * the allocator does not work under these circumstances.
335 */
336RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem);
337
338/**
339 * Resets an event multi semaphore to non-signaled state.
340 *
341 * @returns iprt status code.
342 * @param hEventMultiSem The multiple release event semaphore.
343 */
344RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem);
345
346/**
347 * Wait for the event multi semaphore to be signaled, resume on interruption.
348 *
349 * This function will resume if the wait is interrupted by an async
350 * system event (like a unix signal) or similar.
351 *
352 * @returns iprt status code.
353 * Will not return VERR_INTERRUPTED.
354 * @param hEventMultiSem The multiple release event semaphore.
355 * @param cMillies Number of milliseconds to wait.
356 */
357RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
358
359/**
360 * Wait for the event multi semaphore to be signaled, return on interruption.
361 *
362 * This function will not resume the wait if interrupted.
363 *
364 * @returns iprt status code.
365 * @param hEventMultiSem The multiple release event semaphore.
366 * @param cMillies Number of milliseconds to wait.
367 * @todo Rename to RTSemEventMultiWaitIntr since it is mainly for
368 * ring-0 consumption.
369 */
370RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
371
372/**
373 * Extended API for waiting on an event semaphore to be signaled.
374 *
375 * @returns IPRT status code.
376 * @param hEventMultiSem The multiple release event semaphore to wait
377 * on.
378 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
379 * @param uTimeout The timeout, ignored if
380 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
381 * Whether this is absolute or relative,
382 * milliseconds or nanoseconds depends on the @a
383 * fFlags value. Do not pass RT_INDEFINITE_WAIT
384 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
385 */
386RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout);
387
388/**
389 * Debug version of RTSemEventMultiWaitEx that tracks the location.
390
391 * @returns IPRT status code, see RTSemEventMultiWaitEx.
392 * @param hEventMultiSem The multiple release event semaphore handle.
393 * @param fFlags See RTSemEventMultiWaitEx.
394 * @param uTimeout See RTSemEventMultiWaitEx.
395 * @param uId Some kind of locking location ID. Typically a
396 * return address up the stack. Optional (0).
397 * @param SRC_POS The source position where call is being made
398 * from. Use RT_SRC_POS when possible. Optional.
399 */
400RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
401 RTHCUINTPTR uId, RT_SRC_POS_DECL);
402
403/**
404 * Gets the best timeout resolution that RTSemEventMultiWaitEx can do.
405 *
406 * @returns The resolution in nanoseconds.
407 */
408RTDECL(uint32_t) RTSemEventMultiGetResolution(void);
409
410/**
411 * Sets the signaller thread to one specific thread.
412 *
413 * This is only used for validating usage and deadlock detection. When used
414 * after calls to RTSemEventAddSignaller, the specified thread will be the only
415 * signalling thread.
416 *
417 * @param hEventMultiSem The multiple release event semaphore.
418 * @param hThread The thread that will signal it. Pass
419 * NIL_RTTHREAD to indicate that there is no
420 * special signalling thread.
421 */
422RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
423
424/**
425 * To add more signalling threads.
426 *
427 * First call RTSemEventSetSignaller then add further threads with this.
428 *
429 * @param hEventMultiSem The multiple release event semaphore.
430 * @param hThread The thread that will signal it. NIL_RTTHREAD is
431 * not accepted.
432 */
433RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
434
435/**
436 * To remove a signalling thread.
437 *
438 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
439 *
440 * @param hEventMultiSem The multiple release event semaphore.
441 * @param hThread A previously added thread.
442 */
443RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
444
445/** @} */
446
447
448/** @defgroup grp_rt_sems_mutex RTSemMutex - Mutex semaphores.
449 *
450 * Mutex semaphores protect a section of code or data to which access must be
451 * exclusive. Only one thread can hold access to a critical section at one
452 * time. See RTSemMutexCreate, RTSemMutexRequest and RTSemMutexRelease.
453 *
454 * @remarks These are less efficient than "fast mutexes" and "critical
455 * sections", which IPRT implements as well; see @ref
456 * grp_rt_sems_fast_mutex and @ref grp_rt_critsect .
457 *
458 * @{ */
459
460/**
461 * Create a mutex semaphore.
462 *
463 * @returns iprt status code.
464 * @param phMutexSem Where to store the mutex semaphore handle.
465 */
466RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem);
467
468/**
469 * Creates a read/write semaphore.
470 *
471 * @returns iprt status code.
472 * @param phMutexSem Where to store the handle to the newly created
473 * mutex semaphore.
474 * @param fFlags Flags, any combination of the
475 * RTSEMMUTEX_FLAGS_XXX \#defines.
476 * @param hClass The class (no reference consumed). If NIL, no
477 * lock order validation will be performed on this
478 * lock.
479 * @param uSubClass The sub-class. This is used to define lock
480 * order within a class. RTLOCKVAL_SUB_CLASS_NONE
481 * is the recommended value here.
482 * @param pszNameFmt Name format string for the lock validator,
483 * optional (NULL). Max length is 32 bytes.
484 * @param ... Format string arguments.
485 */
486RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
487 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
488
489/** @name RTSemMutexCreateEx flags
490 * @{ */
491/** Disables lock validation. */
492#define RTSEMMUTEX_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
493/** @} */
494
495
496/**
497 * Destroy a mutex semaphore.
498 *
499 * @returns iprt status code.
500 * @param hMutexSem The mutex semaphore to destroy. NIL is quietly
501 * ignored (VINF_SUCCESS).
502 */
503RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem);
504
505/**
506 * Changes the lock validator sub-class of the mutex semaphore.
507 *
508 * It is recommended to try make sure that nobody is using this semaphore while
509 * changing the value.
510 *
511 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
512 * lock validator isn't compiled in or either of the parameters are
513 * invalid.
514 * @param hMutexSem The handle to the mutex semaphore.
515 * @param uSubClass The new sub-class value.
516 */
517RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass);
518
519/**
520 * Request ownership of a mutex semaphore, resume on interruption.
521 *
522 * This function will resume if the wait is interrupted by an async
523 * system event (like a unix signal) or similar.
524 *
525 * The same thread may request a mutex semaphore multiple times,
526 * a nested counter is kept to make sure it's released on the right
527 * RTSemMutexRelease() call.
528 *
529 * @returns iprt status code.
530 * Will not return VERR_INTERRUPTED.
531 * @param hMutexSem The mutex semaphore to request ownership over.
532 * @param cMillies The number of milliseconds to wait.
533 */
534RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
535
536/**
537 * Request ownership of a mutex semaphore, return on interruption.
538 *
539 * This function will not resume the wait if interrupted.
540 *
541 * The same thread may request a mutex semaphore multiple times,
542 * a nested counter is kept to make sure it's released on the right
543 * RTSemMutexRelease() call.
544 *
545 * @returns iprt status code.
546 * @param hMutexSem The mutex semaphore to request ownership over.
547 * @param cMillies The number of milliseconds to wait.
548 */
549RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
550
551/**
552 * Debug version of RTSemMutexRequest that tracks the location.
553 *
554 * @returns iprt status code.
555 * Will not return VERR_INTERRUPTED.
556 * @param hMutexSem The mutex semaphore to request ownership over.
557 * @param cMillies The number of milliseconds to wait.
558 * @param uId Some kind of locking location ID. Typically a
559 * return address up the stack. Optional (0).
560 * @param SRC_POS The source position where call is being made
561 * from. Use RT_SRC_POS when possible. Optional.
562 */
563RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
564
565/**
566 * Debug version of RTSemMutexRequestNoResume that tracks the location.
567 *
568 * @returns iprt status code.
569 * @param hMutexSem The mutex semaphore to request ownership over.
570 * @param cMillies The number of milliseconds to wait.
571 * @param uId Some kind of locking location ID. Typically a
572 * return address up the stack. Optional (0).
573 * @param SRC_POS The source position where call is being made
574 * from. Use RT_SRC_POS when possible. Optional.
575 */
576RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
577
578/**
579 * Request ownership of a mutex semaphore, extended edition.
580 *
581 * The same thread may request a mutex semaphore multiple times,
582 * a nested counter is kept to make sure it's released on the right
583 * RTSemMutexRelease() call.
584 *
585 * @returns iprt status code.
586 * @param hMutexSem The mutex semaphore to request ownership over.
587 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
588 * @param uTimeout The timeout, ignored if
589 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
590 * Whether this is absolute or relative,
591 * milliseconds or nanoseconds depends on the @a
592 * fFlags value. Do not pass RT_INDEFINITE_WAIT
593 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
594 */
595RTDECL(int) RTSemMutexRequestEx(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout);
596
597/**
598 * Debug version of RTSemMutexRequestEx that tracks the location.
599 *
600 * @returns iprt status code.
601 * @param hMutexSem The mutex semaphore to request ownership over.
602 * @param fFlags See RTSemMutexRequestEx.
603 * @param uTimeout See RTSemMutexRequestEx.
604 * @param uId Some kind of locking location ID. Typically a
605 * return address up the stack. Optional (0).
606 * @param SRC_POS The source position where call is being made
607 * from. Use RT_SRC_POS when possible. Optional.
608 */
609RTDECL(int) RTSemMutexRequestExDebug(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout,
610 RTHCUINTPTR uId, RT_SRC_POS_DECL);
611
612/**
613 * Release the ownership of a mutex semaphore.
614 *
615 * @returns iprt status code.
616 * @param hMutexSem The mutex to release the ownership of. It goes
617 * without saying the the calling thread must own
618 * it.
619 */
620RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem);
621
622/**
623 * Checks if the mutex semaphore is owned or not.
624 *
625 * @returns true if owned, false if not.
626 * @param hMutexSem The mutex semaphore.
627 */
628RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem);
629
630/* Strict build: Remap the two request calls to the debug versions. */
631#if defined(RT_STRICT) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
632# ifdef ___iprt_asm_h
633# define RTSemMutexRequest(hMutexSem, cMillies) RTSemMutexRequestDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
634# define RTSemMutexRequestNoResume(hMutexSem, cMillies) RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
635# define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout) RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
636# else
637# define RTSemMutexRequest(hMutexSem, cMillies) RTSemMutexRequestDebug((hMutexSem), (cMillies), 0, RT_SRC_POS)
638# define RTSemMutexRequestNoResume(hMutexSem, cMillies) RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), 0, RT_SRC_POS)
639# define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout) RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), 0, RT_SRC_POS)
640# endif
641#endif
642
643/* Strict lock order: Automatically classify locks by init location. */
644#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
645# define RTSemMutexCreate(phMutexSem) \
646 RTSemMutexCreateEx((phMutexSem), 0 /*fFlags*/, \
647 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
648 RTLOCKVAL_SUB_CLASS_NONE, NULL)
649#endif
650
651/** @} */
652
653
654/** @defgroup grp_rt_sems_fast_mutex RTSemFastMutex - Fast Mutex Semaphores
655 *
656 * Fast mutexes work like regular mutexes in that they allow only a single
657 * thread access to a critical piece of code or data. As opposed to mutexes,
658 * they require no syscall if the fast mutex is not held (like critical
659 * sections). Unlike critical sections however, they are *not* recursive.
660 *
661 * @remarks The fast mutexes has sideeffects on IRQL on Windows hosts. So use
662 * with care and test on windows with driver verifier.
663 *
664 * @{ */
665
666/**
667 * Create a fast mutex semaphore.
668 *
669 * @returns iprt status code.
670 * @param phFastMtx Where to store the handle to the newly created
671 * fast mutex semaphore.
672 *
673 * @remarks Fast mutex semaphores are not recursive.
674 */
675RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx);
676
677/**
678 * Destroy a fast mutex semaphore.
679 *
680 * @returns iprt status code.
681 * @param hFastMtx Handle to the fast mutex semaphore. NIL is
682 * quietly ignored (VINF_SUCCESS).
683 */
684RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx);
685
686/**
687 * Request ownership of a fast mutex semaphore.
688 *
689 * The same thread may request a mutex semaphore multiple times,
690 * a nested counter is kept to make sure it's released on the right
691 * RTSemMutexRelease() call.
692 *
693 * @returns iprt status code.
694 * @param hFastMtx Handle to the fast mutex semaphore.
695 */
696RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx);
697
698/**
699 * Release the ownership of a fast mutex semaphore.
700 *
701 * @returns iprt status code.
702 * @param hFastMtx Handle to the fast mutex semaphore. It goes
703 * without saying the the calling thread must own
704 * it.
705 */
706RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx);
707
708/** @} */
709
710
711/** @defgroup grp_rt_sems_spin_mutex RTSemSpinMutex - Spinning Mutex Semaphores
712 *
713 * A very adaptive variant of mutex semaphore that is tailored for the ring-0
714 * logger.
715 *
716 * @{ */
717
718/**
719 * Creates a spinning mutex semaphore.
720 *
721 * @returns iprt status code.
722 * @retval VERR_INVALID_PARAMETER on invalid flags.
723 * @retval VERR_NO_MEMORY if out of memory for the semaphore structure and
724 * handle.
725 *
726 * @param phSpinMtx Where to return the handle to the create semaphore.
727 * @param fFlags Flags, see RTSEMSPINMUTEX_FLAGS_XXX.
728 */
729RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags);
730
731/** @name RTSemSpinMutexCreate flags.
732 * @{ */
733/** Always take the semaphore in a IRQ safe way.
734 * (In plain words: always disable interrupts.) */
735#define RTSEMSPINMUTEX_FLAGS_IRQ_SAFE RT_BIT_32(0)
736/** Mask of valid flags. */
737#define RTSEMSPINMUTEX_FLAGS_VALID_MASK UINT32_C(0x00000001)
738/** @} */
739
740/**
741 * Destroys a spinning mutex semaphore.
742 *
743 * @returns iprt status code.
744 * @retval VERR_INVALID_HANDLE (or crash) if the handle is invalid. (NIL will
745 * not cause this status.)
746 *
747 * @param hSpinMtx The semaphore handle. NIL_RTSEMSPINMUTEX is ignored
748 * quietly (VINF_SUCCESS).
749 */
750RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx);
751
752/**
753 * Request the spinning mutex semaphore.
754 *
755 * This may block if the context we're called in allows this. If not it will
756 * spin. If called in an interrupt context, we will only spin if the current
757 * owner isn't interrupted. Also, on some systems it is not always possible to
758 * wake up blocking threads in all contexts, so, which will either be indicated
759 * by returning VERR_SEM_BAD_CONTEXT or by temporarily switching the semaphore
760 * into pure spinlock state.
761 *
762 * Preemption will be disabled upon return. IRQs may also be disabled.
763 *
764 * @returns iprt status code.
765 * @retval VERR_SEM_BAD_CONTEXT if the context it's called in isn't suitable
766 * for releasing it if someone is sleeping on it.
767 * @retval VERR_SEM_DESTROYED if destroyed.
768 * @retval VERR_SEM_NESTED if held by the caller. Asserted.
769 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted
770 *
771 * @param hSpinMtx The semaphore handle.
772 */
773RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx);
774
775/**
776 * Like RTSemSpinMutexRequest but it won't block or spin if the semaphore is
777 * held by someone else.
778 *
779 * @returns iprt status code.
780 * @retval VERR_SEM_BUSY if held by someone else.
781 * @retval VERR_SEM_DESTROYED if destroyed.
782 * @retval VERR_SEM_NESTED if held by the caller. Asserted.
783 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted
784 *
785 * @param hSpinMtx The semaphore handle.
786 */
787RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx);
788
789/**
790 * Releases the semaphore previously acquired by RTSemSpinMutexRequest or
791 * RTSemSpinMutexTryRequest.
792 *
793 * @returns iprt status code.
794 * @retval VERR_SEM_DESTROYED if destroyed.
795 * @retval VERR_NOT_OWNER if not owner. Asserted.
796 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted.
797 *
798 * @param hSpinMtx The semaphore handle.
799 */
800RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx);
801
802/** @} */
803
804
805/** @defgroup grp_rt_sem_rw RTSemRW - Read / Write Semaphores
806 *
807 * Read/write semaphores are a fancier version of mutexes in that they grant
808 * read access to the protected data to several threads at the same time but
809 * allow only one writer at a time. This can make code scale better at the
810 * expense of slightly more overhead in mutex management.
811 *
812 * @{ */
813
814/**
815 * Creates a read/write semaphore.
816 *
817 * @returns iprt status code.
818 * @param phRWSem Where to store the handle to the newly created
819 * RW semaphore.
820 */
821RTDECL(int) RTSemRWCreate(PRTSEMRW phRWSem);
822
823/**
824 * Creates a read/write semaphore.
825 *
826 * @returns iprt status code.
827 * @param phRWSem Where to store the handle to the newly created
828 * RW semaphore.
829 * @param fFlags Flags, any combination of the RTSEMRW_FLAGS_XXX
830 * \#defines.
831 * @param hClass The class (no reference consumed). If NIL, no
832 * lock order validation will be performed on this
833 * lock.
834 * @param uSubClass The sub-class. This is used to define lock
835 * order within a class. RTLOCKVAL_SUB_CLASS_NONE
836 * is the recommended value here.
837 * @param pszNameFmt Name format string for the lock validator,
838 * optional (NULL). Max length is 32 bytes.
839 * @param ... Format string arguments.
840 */
841RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
842 const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
843
844/** @name RTSemRWCreateEx flags
845 * @{ */
846/** Disables lock validation. */
847#define RTSEMRW_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
848/** @} */
849
850/**
851 * Destroys a read/write semaphore.
852 *
853 * @returns iprt status code.
854 * @param hRWSem Handle to the read/write semaphore. NIL is
855 * quietly ignored (VINF_SUCCESS).
856 */
857RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem);
858
859/**
860 * Changes the lock validator sub-class of the read/write semaphore.
861 *
862 * It is recommended to try make sure that nobody is using this semaphore while
863 * changing the value.
864 *
865 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
866 * lock validator isn't compiled in or either of the parameters are
867 * invalid.
868 * @param hRWSem Handle to the read/write semaphore.
869 * @param uSubClass The new sub-class value.
870 */
871RTDECL(uint32_t) RTSemRWSetSubClass(RTSEMRW hRWSem, uint32_t uSubClass);
872
873/**
874 * Request read access to a read/write semaphore, resume on interruption
875 *
876 * @returns iprt status code.
877 * @retval VINF_SUCCESS on success.
878 * @retval VERR_INTERRUPT if the wait was interrupted.
879 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
880 *
881 * @param hRWSem Handle to the read/write semaphore.
882 * @param cMillies The number of milliseconds to wait.
883 */
884RTDECL(int) RTSemRWRequestRead(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
885
886/**
887 * Request read access to a read/write semaphore, return on interruption
888 *
889 * @returns iprt status code.
890 * @retval VINF_SUCCESS on success.
891 * @retval VERR_INTERRUPT if the wait was interrupted.
892 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
893 *
894 * @param hRWSem Handle to the read/write semaphore.
895 * @param cMillies The number of milliseconds to wait.
896 */
897RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
898
899/**
900 * Debug version of RTSemRWRequestRead that tracks the location.
901 *
902 * @returns iprt status code.
903 * @retval VINF_SUCCESS on success.
904 * @retval VERR_INTERRUPT if the wait was interrupted.
905 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
906 *
907 * @param hRWSem Handle to the read/write semaphore.
908 * @param cMillies The number of milliseconds to wait.
909 * @param uId Some kind of locking location ID. Typically a
910 * return address up the stack. Optional (0).
911 * @param SRC_POS The source position where call is being made
912 * from. Use RT_SRC_POS when possible. Optional.
913 */
914RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
915
916/**
917 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
918 *
919 * @returns iprt status code.
920 * @retval VINF_SUCCESS on success.
921 * @retval VERR_INTERRUPT if the wait was interrupted.
922 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
923 *
924 * @param hRWSem Handle to the read/write semaphore.
925 * @param cMillies The number of milliseconds to wait.
926 * @param uId Some kind of locking location ID. Typically a
927 * return address up the stack. Optional (0).
928 * @param SRC_POS The source position where call is being made
929 * from. Use RT_SRC_POS when possible. Optional.
930 */
931RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
932
933/**
934 * Request read access to a read/write semaphore, extended edition.
935 *
936 * @returns iprt status code.
937 * @retval VINF_SUCCESS on success.
938 * @retval VERR_INTERRUPT if the wait was interrupted.
939 * @retval VERR_TIMEOUT if the wait timed out.
940 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
941 *
942 * @param hRWSem Handle to the read/write semaphore.
943 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
944 * @param uTimeout The timeout, ignored if
945 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
946 * Whether this is absolute or relative,
947 * milliseconds or nanoseconds depends on the @a
948 * fFlags value. Do not pass RT_INDEFINITE_WAIT
949 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
950 */
951RTDECL(int) RTSemRWRequestReadEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout);
952
953
954/**
955 * Debug version of RTSemRWRequestReadEx that tracks the location.
956 *
957 * @returns iprt status code.
958 * @retval VINF_SUCCESS on success.
959 * @retval VERR_INTERRUPT if the wait was interrupted.
960 * @retval VERR_TIMEOUT if the wait timed out.
961 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
962 *
963 * @param hRWSem Handle to the read/write semaphore.
964 * @param fFlags See RTSemRWRequestReadEx.
965 * @param uTimeout See RTSemRWRequestReadEx.
966 * @param uId Some kind of locking location ID. Typically a
967 * return address up the stack. Optional (0).
968 * @param SRC_POS The source position where call is being made
969 * from. Use RT_SRC_POS when possible. Optional.
970 */
971RTDECL(int) RTSemRWRequestReadExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout,
972 RTHCUINTPTR uId, RT_SRC_POS_DECL);
973
974/**
975 * Release read access to a read/write semaphore.
976 *
977 * @returns iprt status code.
978 * @param hRWSem Handle to the read/write semaphore. It goes
979 * without saying that caller must own read
980 * privileges to the semaphore.
981 */
982RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem);
983
984/**
985 * Request write access to a read/write semaphore, resume on interruption.
986 *
987 * @returns iprt status code.
988 * @retval VINF_SUCCESS on success.
989 * @retval VERR_DEADLOCK if the caller owned the read lock.
990 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
991 *
992 * @param hRWSem Handle to the read/write semaphore.
993 * @param cMillies The number of milliseconds to wait.
994 */
995RTDECL(int) RTSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
996
997/**
998 * Request write access to a read/write semaphore, return on interruption.
999 *
1000 * @returns iprt status code.
1001 * @retval VINF_SUCCESS on success.
1002 * @retval VERR_INTERRUPT if the wait was interrupted.
1003 * @retval VERR_DEADLOCK if the caller owned the read lock.
1004 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
1005 *
1006 * @param hRWSem Handle to the read/write semaphore.
1007 * @param cMillies The number of milliseconds to wait.
1008 */
1009RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
1010
1011/**
1012 * Debug version of RTSemRWRequestWrite that tracks the location.
1013 *
1014 * @returns IPRT status code, see RTSemRWRequestWrite.
1015 * @param hRWSem Handle to the read/write semaphore.
1016 * @param cMillies The number of milliseconds to wait.
1017 * @param uId Some kind of locking location ID. Typically a
1018 * return address up the stack. Optional (0).
1019 * @param SRC_POS The source position where call is being made
1020 * from. Use RT_SRC_POS when possible. Optional.
1021 */
1022RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
1023
1024/**
1025 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
1026 *
1027 * @returns IPRT status code, see RTSemRWRequestWriteNoResume.
1028 * @param hRWSem Handle to the read/write semaphore.
1029 * @param cMillies The number of milliseconds to wait.
1030 * @param uId Some kind of locking location ID. Typically a
1031 * return address up the stack. Optional (0).
1032 * @param SRC_POS The source position where call is being made
1033 * from. Use RT_SRC_POS when possible. Optional.
1034 */
1035RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
1036
1037/**
1038 * Request write access to a read/write semaphore, extended edition.
1039 *
1040 * @returns iprt status code.
1041 * @retval VINF_SUCCESS on success.
1042 * @retval VERR_INTERRUPTED if the wait was interrupted.
1043 * @retval VERR_TIMEOUT if the wait timed out.
1044 * @retval VERR_DEADLOCK if the caller owned the read lock. Do not depend on
1045 * this as it is implementation specific.
1046 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
1047 *
1048 * @param hRWSem Handle to the read/write semaphore.
1049 * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX.
1050 * @param uTimeout The timeout, ignored if
1051 * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags.
1052 * Whether this is absolute or relative,
1053 * milliseconds or nanoseconds depends on the @a
1054 * fFlags value. Do not pass RT_INDEFINITE_WAIT
1055 * here, use RTSEMWAIT_FLAGS_INDEFINITE instead.
1056 */
1057RTDECL(int) RTSemRWRequestWriteEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout);
1058
1059/**
1060 * Debug version of RTSemRWRequestWriteEx that tracks the location.
1061 *
1062 * @returns IPRT status code, see RTSemRWRequestWriteEx.
1063 * @param hRWSem Handle to the read/write semaphore.
1064 * @param fFlags See RTSemRWRequestWriteEx.
1065 * @param uTimeout See RTSemRWRequestWriteEx.
1066 * @param uId Some kind of locking location ID. Typically a
1067 * return address up the stack. Optional (0).
1068 * @param SRC_POS The source position where call is being made
1069 * from. Use RT_SRC_POS when possible. Optional.
1070 */
1071RTDECL(int) RTSemRWRequestWriteExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout,
1072 RTHCUINTPTR uId, RT_SRC_POS_DECL);
1073
1074/**
1075 * Release write access to a read/write semaphore.
1076 *
1077 * @returns iprt status code.
1078 * @param hRWSem Handle to the read/write semaphore. Goes
1079 * without saying that caller must have write
1080 * access to the semaphore.
1081 */
1082RTDECL(int) RTSemRWReleaseWrite(RTSEMRW hRWSem);
1083
1084/**
1085 * Checks if the caller is the exclusive semaphore owner.
1086 *
1087 * @returns true / false accoringly.
1088 * @param hRWSem Handle to the read/write semaphore.
1089 */
1090RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW hRWSem);
1091
1092/**
1093 * Checks if the caller is one of the read owners of the semaphore.
1094 *
1095 * @note !CAUTION! This API doesn't work reliably if lock validation isn't
1096 * enabled. Meaning, the answer is not trustworhty unless
1097 * RT_LOCK_STRICT or RTSEMRW_STRICT was defined at build time. Also,
1098 * make sure you do not use RTSEMRW_FLAGS_NO_LOCK_VAL when creating
1099 * the semaphore. And finally, if you used a locking class, don't
1100 * disable deadlock detection by setting cMsMinDeadlock to
1101 * RT_INDEFINITE_WAIT.
1102 *
1103 * In short, only use this for assertions.
1104 *
1105 * @returns true if reader, false if not.
1106 * @param hRWSem Handle to the read/write semaphore.
1107 * @param fWannaHear What you'd like to hear when lock validation is
1108 * not available. (For avoiding asserting all over
1109 * the place.)
1110 */
1111RTDECL(bool) RTSemRWIsReadOwner(RTSEMRW hRWSem, bool fWannaHear);
1112
1113/**
1114 * Gets the write recursion count.
1115 *
1116 * @returns The write recursion count (0 if bad semaphore handle).
1117 * @param hRWSem Handle to the read/write semaphore.
1118 */
1119RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem);
1120
1121/**
1122 * Gets the read recursion count of the current writer.
1123 *
1124 * @returns The read recursion count (0 if bad semaphore handle).
1125 * @param hRWSem Handle to the read/write semaphore.
1126 */
1127RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem);
1128
1129/**
1130 * Gets the current number of reads.
1131 *
1132 * This includes all read recursions, so it might be higher than the number of
1133 * read owners. It does not include reads done by the current writer.
1134 *
1135 * @returns The read count (0 if bad semaphore handle).
1136 * @param hRWSem Handle to the read/write semaphore.
1137 */
1138RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem);
1139
1140/* Strict build: Remap the four request calls to the debug versions. */
1141#if defined(RT_STRICT) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
1142# ifdef ___iprt_asm_h
1143# define RTSemRWRequestRead(hRWSem, cMillies) RTSemRWRequestReadDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1144# define RTSemRWRequestReadNoResume(hRWSem, cMillies) RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1145# define RTSemRWRequestWrite(hRWSem, cMillies) RTSemRWRequestWriteDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1146# define RTSemRWRequestWriteNoResume(hRWSem, cMillies) RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1147# define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout) RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
1148# else
1149# define RTSemRWRequestRead(hRWSem, cMillies) RTSemRWRequestReadDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1150# define RTSemRWRequestReadNoResume(hRWSem, cMillies) RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1151# define RTSemRWRequestWrite(hRWSem, cMillies) RTSemRWRequestWriteDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1152# define RTSemRWRequestWriteNoResume(hRWSem, cMillies) RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS)
1153# define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout) RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), 0, RT_SRC_POS)
1154# endif
1155#endif
1156
1157/* Strict lock order: Automatically classify locks by init location. */
1158#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
1159# define RTSemRWCreate(phSemRW) \
1160 RTSemRWCreateEx((phSemRW), 0 /*fFlags*/, \
1161 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
1162 RTLOCKVAL_SUB_CLASS_NONE, NULL)
1163#endif
1164
1165/** @} */
1166
1167
1168/** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct
1169 *
1170 * Serialization of a two way communication.
1171 *
1172 * @{ */
1173
1174/**
1175 * Ping-pong speaker
1176 */
1177typedef enum RTPINGPONGSPEAKER
1178{
1179 /** Not initialized. */
1180 RTPINGPONGSPEAKER_UNINITIALIZE = 0,
1181 /** Ping is speaking, Pong is waiting. */
1182 RTPINGPONGSPEAKER_PING,
1183 /** Pong is signaled, Ping is waiting. */
1184 RTPINGPONGSPEAKER_PONG_SIGNALED,
1185 /** Pong is speaking, Ping is waiting. */
1186 RTPINGPONGSPEAKER_PONG,
1187 /** Ping is signaled, Pong is waiting. */
1188 RTPINGPONGSPEAKER_PING_SIGNALED,
1189 /** Hack to ensure that it's at least 32-bits wide. */
1190 RTPINGPONGSPEAKER_HACK = 0x7fffffff
1191} RTPINGPONGSPEAKER;
1192
1193/**
1194 * Ping-Pong construct.
1195 *
1196 * Two threads, one saying Ping and the other saying Pong. The construct
1197 * makes sure they don't speak out of turn and that they can wait and poll
1198 * on the conversation.
1199 */
1200typedef struct RTPINGPONG
1201{
1202 /** The semaphore the Ping thread waits on. */
1203 RTSEMEVENT Ping;
1204 /** The semaphore the Pong thread waits on. */
1205 RTSEMEVENT Pong;
1206 /** The current speaker. */
1207 volatile RTPINGPONGSPEAKER enmSpeaker;
1208#if HC_ARCH_BITS == 64
1209 /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
1210 uint32_t u32Padding;
1211#endif
1212} RTPINGPONG;
1213/** Pointer to Ping-Pong construct. */
1214typedef RTPINGPONG *PRTPINGPONG;
1215
1216/**
1217 * Init a Ping-Pong construct.
1218 *
1219 * @returns iprt status code.
1220 * @param pPP Pointer to the ping-pong structure which needs initialization.
1221 */
1222RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
1223
1224/**
1225 * Deletes a Ping-Pong construct.
1226 *
1227 * @returns iprt status code.
1228 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
1229 * (I.e. put into uninitialized state.)
1230 */
1231RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
1232
1233/**
1234 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
1235 * This is called by the ping thread.
1236 *
1237 * @returns iprt status code.
1238 * @param pPP Pointer to the ping-pong structure to ping.
1239 */
1240RTDECL(int) RTSemPing(PRTPINGPONG pPP);
1241
1242/**
1243 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
1244 * This is called by the pong thread.
1245 *
1246 * @returns iprt status code.
1247 * @param pPP Pointer to the ping-pong structure to pong.
1248 */
1249RTDECL(int) RTSemPong(PRTPINGPONG pPP);
1250
1251/**
1252 * Wait function for the ping thread.
1253 *
1254 * @returns iprt status code.
1255 * Will not return VERR_INTERRUPTED.
1256 * @param pPP Pointer to the ping-pong structure to wait on.
1257 * @param cMillies Number of milliseconds to wait.
1258 */
1259RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
1260
1261/**
1262 * Wait function for the pong thread.
1263 *
1264 * @returns iprt status code.
1265 * Will not return VERR_INTERRUPTED.
1266 * @param pPP Pointer to the ping-pong structure to wait on.
1267 * @param cMillies Number of milliseconds to wait.
1268 */
1269RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
1270
1271
1272/**
1273 * Checks if the pong thread is speaking.
1274 *
1275 * @returns true / false.
1276 * @param pPP Pointer to the ping-pong structure.
1277 * @remark This is NOT the same as !RTSemPongIsSpeaker().
1278 */
1279DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
1280{
1281 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1282 return enmSpeaker == RTPINGPONGSPEAKER_PING;
1283}
1284
1285
1286/**
1287 * Checks if the pong thread is speaking.
1288 *
1289 * @returns true / false.
1290 * @param pPP Pointer to the ping-pong structure.
1291 * @remark This is NOT the same as !RTSemPingIsSpeaker().
1292 */
1293DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
1294{
1295 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1296 return enmSpeaker == RTPINGPONGSPEAKER_PONG;
1297}
1298
1299
1300/**
1301 * Checks whether the ping thread should wait.
1302 *
1303 * @returns true / false.
1304 * @param pPP Pointer to the ping-pong structure.
1305 * @remark This is NOT the same as !RTSemPongShouldWait().
1306 */
1307DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
1308{
1309 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1310 return enmSpeaker == RTPINGPONGSPEAKER_PONG
1311 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
1312 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
1313}
1314
1315
1316/**
1317 * Checks whether the pong thread should wait.
1318 *
1319 * @returns true / false.
1320 * @param pPP Pointer to the ping-pong structure.
1321 * @remark This is NOT the same as !RTSemPingShouldWait().
1322 */
1323DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
1324{
1325 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1326 return enmSpeaker == RTPINGPONGSPEAKER_PING
1327 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
1328 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
1329}
1330
1331/** @} */
1332
1333
1334/** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads
1335 *
1336 * The crossroads semaphore is intended to prevent two classes of incompatible
1337 * events from occurring simultaneously, like south/north bound traffic and
1338 * west/east bound traffic at a 4-way junction.
1339 *
1340 * @remarks In order to simplify the implementation, the current flow is always
1341 * given priority. So, it won't work at all well when busy!
1342 *
1343 * @remarks "XRoads" is used as a name because it is briefer than "crossroads"
1344 * and it slightly stresses that is a 4 way crossing to the users of
1345 * American English.
1346 * @{
1347 */
1348
1349/**
1350 * Creates a crossroads semaphore.
1351 *
1352 * @returns IPRT status code.
1353 *
1354 * @param phXRoads Where to return the handle to the newly created
1355 * crossroads semaphore.
1356 */
1357RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads);
1358
1359/**
1360 * Destroys a crossroads semaphore.
1361 *
1362 * @returns IPRT status code.
1363 *
1364 * @param hXRoads Handle to the crossroads semaphore that is to be
1365 * destroyed. NIL_RTSEMXROADS is quitetly ignored
1366 * (VINF_SUCCESS).
1367 */
1368RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads);
1369
1370/**
1371 * Enter the crossroads from the south or north.
1372 *
1373 * (Coupled with RTSemXRoadsNSLeave.)
1374 *
1375 * @returns IPRT status code.
1376 * @param hXRoads Handle to the crossroads semaphore.
1377 */
1378RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads);
1379
1380/**
1381 * Leave the crossroads to the north or south.
1382 *
1383 * (Coupled with RTSemXRoadsNSEnter.)
1384 *
1385 * @returns IPRT status code.
1386 * @param hXRoads Handle to the crossroads semaphore.
1387 */
1388RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads);
1389
1390/**
1391 * Leave the crossroads from the east or west.
1392 *
1393 * (Coupled with RTSemXRoadsEWLeave.)
1394 *
1395 * @returns IPRT status code.
1396 * @param hXRoads Handle to the crossroads semaphore.
1397 */
1398RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads);
1399
1400/**
1401 * Leave the crossroads to the west or east.
1402 *
1403 * (Coupled with RTSemXRoadsEWEnter.)
1404 *
1405 * @returns IPRT status code.
1406 * @param hXRoads Handle to the crossroads semaphore.
1407 */
1408RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads);
1409
1410/** @} */
1411
1412/** @} */
1413
1414RT_C_DECLS_END
1415
1416#endif
1417
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette