VirtualBox

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

Last change on this file since 92059 was 90488, checked in by vboxsync, 3 years ago

IPRT: Added RTSemEventIsSignalSafe and RTSemEventMultiIsSignalSafe - ring-0 only. bugref:6695

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