VirtualBox

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

Last change on this file since 103224 was 98103, checked in by vboxsync, 21 months ago

Copyright year updates by scm.

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