VirtualBox

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

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

*: scm --fix-header-guard-endif

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