VirtualBox

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

Last change on this file since 25724 was 25724, checked in by vboxsync, 15 years ago

iprt: Use RTMSINTERVAL for timeouts. Fixed missing timeout underflow checks in two RTFileAioCtxWait implementations.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.7 KB
Line 
1/** @file
2 * IPRT - Semaphore.
3 */
4
5/*
6 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
27 * additional information or have any questions.
28 */
29
30#ifndef ___iprt_semaphore_h
31#define ___iprt_semaphore_h
32
33#include <iprt/cdefs.h>
34#include <iprt/types.h>
35
36
37RT_C_DECLS_BEGIN
38
39/** @defgroup grp_rt_sems RTSem - Semaphores
40 *
41 * This module implements all kinds of event and mutex semaphores; in addition
42 * to these, IPRT implements "critical sections", which are fast recursive
43 * mutexes (see @ref grp_rt_critsect ). C++ users may find @ref grp_rt_lock
44 * interesting.
45 *
46 * @ingroup grp_rt
47 * @{
48 */
49
50
51/** @defgroup grp_rt_sems_event RTSemEvent - Single Release Event Semaphores
52 *
53 * Event semaphores can be used for inter-thread communication when one thread
54 * wants to notify another thread that something happened. A thread can block
55 * ("wait") on an event semaphore until it is signalled by another thread; see
56 * RTSemEventCreate, RTSemEventSignal and RTSemEventWait.
57 *
58 * @{ */
59
60/**
61 * Create an event semaphore.
62 *
63 * @returns iprt status code.
64 * @param phEventSem Where to store the handle to the newly created
65 * event semaphore.
66 */
67RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem);
68
69/**
70 * Create an event semaphore.
71 *
72 * @returns iprt status code.
73 * @param phEventSem Where to store the handle to the newly created
74 * event semaphore.
75 * @param fFlags Flags, any combination of the
76 * RTSEMEVENT_FLAGS_XXX \#defines.
77 * @param hClass The class (no reference consumed). Since we
78 * don't do order checks on event semaphores, the
79 * use of the class is limited to controlling the
80 * timeout threshold for deadlock detection.
81 * @param pszNameFmt Name format string for the lock validator,
82 * optional (NULL). Max length is 32 bytes.
83 * @param ... Format string arguments.
84 */
85RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...);
86
87/** @name RTSemMutexCreateEx flags
88 * @{ */
89/** Disables lock validation. */
90#define RTSEMEVENT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
91/** @} */
92
93/**
94 * Destroy an event semaphore.
95 *
96 * @returns iprt status code.
97 * @param hEventSem Handle of the event sempahore. NIL_RTSEMEVENT
98 * is quitely ignored (VINF_SUCCESS).
99 */
100RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem);
101
102/**
103 * Signal an event semaphore.
104 *
105 * The event semaphore will be signaled and automatically reset after exactly
106 * one thread have successfully returned from RTSemEventWait() after
107 * waiting/polling on that semaphore.
108 *
109 * @returns iprt status code.
110 * @param hEventSem The event semaphore to signal.
111 */
112RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem);
113
114/**
115 * Wait for the event semaphore to be signaled, resume on interruption.
116 *
117 * This function will resume if the wait is interrupted by an async system event
118 * (like a unix signal) or similar.
119 *
120 * @returns iprt status code.
121 * Will not return VERR_INTERRUPTED.
122 * @param hEventSem The event semaphore to wait on.
123 * @param cMillies Number of milliseconds to wait.
124 */
125RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
126
127/**
128 * Wait for the event semaphore to be signaled, return on interruption.
129 *
130 * This function will not resume the wait if interrupted.
131 *
132 * @returns iprt status code.
133 * @param hEventSem The event semaphore to wait on.
134 * @param cMillies Number of milliseconds to wait.
135 */
136RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies);
137
138/**
139 * Sets the signaller thread to one specific thread.
140 *
141 * This is only used for validating usage and deadlock detection. When used
142 * after calls to RTSemEventAddSignaller, the specified thread will be the only
143 * signalling thread.
144 *
145 * @param hEventSem The event semaphore.
146 * @param hThread The thread that will signal it. Pass
147 * NIL_RTTHREAD to indicate that there is no
148 * special signalling thread.
149 */
150RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
151
152/**
153 * To add more signalling threads.
154 *
155 * First call RTSemEventSetSignaller then add further threads with this.
156 *
157 * @param hEventSem The event semaphore.
158 * @param hThread The thread that will signal it. NIL_RTTHREAD is
159 * not accepted.
160 */
161RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
162
163/**
164 * To remove a signalling thread.
165 *
166 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
167 *
168 * @param hEventSem The event semaphore.
169 * @param hThread A previously added thread.
170 */
171RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);
172
173/** @} */
174
175
176/** @defgroup grp_rt_sems_event_multi RTSemEventMulti - Multiple Release Event Semaphores
177 *
178 * A variant of @ref grp_rt_sems_event where all threads will be unblocked when
179 * signalling the semaphore.
180 *
181 * @{ */
182
183/**
184 * Creates a multiple release event semaphore.
185 *
186 * @returns iprt status code.
187 * @param phEventMultiSem Where to store the handle to the newly created
188 * multiple release event semaphore.
189 */
190RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem);
191
192/**
193 * Creates a multiple release event semaphore.
194 *
195 * @returns iprt status code.
196 * @param phEventMultiSem Where to store the handle to the newly created
197 * multiple release event semaphore.
198 * @param fFlags Flags, any combination of the
199 * RTSEMEVENTMULTI_FLAGS_XXX \#defines.
200 * @param hClass The class (no reference consumed). Since we
201 * don't do order checks on event semaphores, the
202 * use of the class is limited to controlling the
203 * timeout threshold for deadlock detection.
204 * @param pszNameFmt Name format string for the lock validator,
205 * optional (NULL). Max length is 32 bytes.
206 * @param ... Format string arguments.
207 */
208RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
209 const char *pszNameFmt, ...);
210
211/** @name RTSemMutexCreateEx flags
212 * @{ */
213/** Disables lock validation. */
214#define RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
215/** @} */
216
217/**
218 * Destroy an event multi semaphore.
219 *
220 * @returns iprt status code.
221 * @param hEventMultiSem The multiple release event sempahore. NIL is
222 * quietly ignored (VINF_SUCCESS).
223 */
224RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem);
225
226/**
227 * Signal an event multi semaphore.
228 *
229 * @returns iprt status code.
230 * @param hEventMultiSem The multiple release event sempahore.
231 */
232RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem);
233
234/**
235 * Resets an event multi semaphore to non-signaled state.
236 *
237 * @returns iprt status code.
238 * @param hEventMultiSem The multiple release event sempahore.
239 */
240RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem);
241
242/**
243 * Wait for the event multi semaphore to be signaled, resume on interruption.
244 *
245 * This function will resume if the wait is interrupted by an async
246 * system event (like a unix signal) or similar.
247 *
248 * @returns iprt status code.
249 * Will not return VERR_INTERRUPTED.
250 * @param hEventMultiSem The multiple release event sempahore.
251 * @param cMillies Number of milliseconds to wait.
252 */
253RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
254
255
256/**
257 * Wait for the event multi semaphore to be signaled, return on interruption.
258 *
259 * This function will not resume the wait if interrupted.
260 *
261 * @returns iprt status code.
262 * @param hEventMultiSem The multiple release event sempahore.
263 * @param cMillies Number of milliseconds to wait.
264 */
265RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
266
267/**
268 * Sets the signaller thread to one specific thread.
269 *
270 * This is only used for validating usage and deadlock detection. When used
271 * after calls to RTSemEventAddSignaller, the specified thread will be the only
272 * signalling thread.
273 *
274 * @param hEventMultiSem The multiple release event semaphore.
275 * @param hThread The thread that will signal it. Pass
276 * NIL_RTTHREAD to indicate that there is no
277 * special signalling thread.
278 */
279RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
280
281/**
282 * To add more signalling threads.
283 *
284 * First call RTSemEventSetSignaller then add further threads with this.
285 *
286 * @param hEventMultiSem The multiple release event semaphore.
287 * @param hThread The thread that will signal it. NIL_RTTHREAD is
288 * not accepted.
289 */
290RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
291
292/**
293 * To remove a signalling thread.
294 *
295 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller.
296 *
297 * @param hEventMultiSem The multiple release event semaphore.
298 * @param hThread A previously added thread.
299 */
300RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread);
301
302/** @} */
303
304
305/** @defgroup grp_rt_sems_mutex RTSemMutex - Mutex semaphores.
306 *
307 * Mutex semaphores protect a section of code or data to which access must be
308 * exclusive. Only one thread can hold access to a critical section at one
309 * time. See RTSemMutexCreate, RTSemMutexRequest and RTSemMutexRelease.
310 *
311 * @remarks These are less efficient than "fast mutexes" and "critical
312 * sections", which IPRT implements as well; see @ref
313 * grp_rt_sems_fast_mutex and @ref grp_rt_critsect .
314 *
315 * @{ */
316
317/**
318 * Create a mutex semaphore.
319 *
320 * @returns iprt status code.
321 * @param phMutexSem Where to store the mutex semaphore handle.
322 */
323RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem);
324
325/**
326 * Creates a read/write semaphore.
327 *
328 * @returns iprt status code.
329 * @param phRWSem Where to store the handle to the newly created
330 * RW semaphore.
331 * @param fFlags Flags, any combination of the
332 * RTSEMMUTEX_FLAGS_XXX \#defines.
333 * @param hClass The class (no reference consumed). If NIL, no
334 * lock order validation will be performed on this
335 * lock.
336 * @param uSubClass The sub-class. This is used to define lock
337 * order within a class. RTLOCKVAL_SUB_CLASS_NONE
338 * is the recommended value here.
339 * @param pszNameFmt Name format string for the lock validator,
340 * optional (NULL). Max length is 32 bytes.
341 * @param ... Format string arguments.
342 */
343RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
344 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...);
345
346/** @name RTSemMutexCreateEx flags
347 * @{ */
348/** Disables lock validation. */
349#define RTSEMMUTEX_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
350/** @} */
351
352
353/**
354 * Destroy a mutex semaphore.
355 *
356 * @returns iprt status code.
357 * @param hMutexSem The mutex semaphore to destroy. NIL is quitely
358 * ignored (VINF_SUCCESS).
359 */
360RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem);
361
362/**
363 * Changes the lock validator sub-class of the mutex semaphore.
364 *
365 * It is recommended to try make sure that nobody is using this sempahore while
366 * changing the value.
367 *
368 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
369 * lock validator isn't compiled in or either of the parameters are
370 * invalid.
371 * @param hMutexSem The handle to the mutex semaphore.
372 * @param uSubClass The new sub-class value.
373 */
374RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass);
375
376/**
377 * Request ownership of a mutex semaphore, resume on interruption.
378 *
379 * This function will resume if the wait is interrupted by an async
380 * system event (like a unix signal) or similar.
381 *
382 * The same thread may request a mutex semaphore multiple times,
383 * a nested counter is kept to make sure it's released on the right
384 * RTSemMutexRelease() call.
385 *
386 * @returns iprt status code.
387 * Will not return VERR_INTERRUPTED.
388 * @param hMutexSem The mutex semaphore to request ownership over.
389 * @param cMillies The number of milliseconds to wait.
390 */
391RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
392
393/**
394 * Request ownership of a mutex semaphore, return on interruption.
395 *
396 * This function will not resume the wait if interrupted.
397 *
398 * The same thread may request a mutex semaphore multiple times,
399 * a nested counter is kept to make sure it's released on the right
400 * RTSemMutexRelease() call.
401 *
402 * @returns iprt status code.
403 * @param hMutexSem The mutex semaphore to request ownership over.
404 * @param cMillies The number of milliseconds to wait.
405 */
406RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies);
407
408/**
409 * Debug version of RTSemMutexRequest that tracks the location.
410 *
411 * @returns iprt status code.
412 * Will not return VERR_INTERRUPTED.
413 * @param hMutexSem The mutex semaphore to request ownership over.
414 * @param cMillies The number of milliseconds to wait.
415 * @param uId Some kind of locking location ID. Typically a
416 * return address up the stack. Optional (0).
417 * @param pszFile The file where the lock is being acquired from.
418 * Optional.
419 * @param iLine The line number in that file. Optional (0).
420 * @param pszFunction The functionn where the lock is being acquired
421 * from. Optional.
422 */
423RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
424
425/**
426 * Debug version of RTSemMutexRequestNoResume that tracks the location.
427 *
428 * @returns iprt status code.
429 * @param hMutexSem The mutex semaphore to request ownership over.
430 * @param cMillies The number of milliseconds to wait.
431 * @param uId Some kind of locking location ID. Typically a
432 * return address up the stack. Optional (0).
433 * @param pszFile The file where the lock is being acquired from.
434 * Optional.
435 * @param iLine The line number in that file. Optional (0).
436 * @param pszFunction The functionn where the lock is being acquired
437 * from. Optional.
438 */
439RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
440
441/**
442 * Release the ownership of a mutex semaphore.
443 *
444 * @returns iprt status code.
445 * @param hMutexSem The mutex to release the ownership of. It goes
446 * without saying the the calling thread must own
447 * it.
448 */
449RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem);
450
451/**
452 * Checks if the mutex semaphore is owned or not.
453 *
454 * @returns true if owned, false if not.
455 * @param hMutexSem The mutex semaphore.
456 */
457RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem);
458
459/* Strict build: Remap the two request calls to the debug versions. */
460#ifdef RT_STRICT
461# ifdef ___iprt_asm_h
462# define RTSemMutexRequest(pCritSect, cMillies) RTSemMutexRequestDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
463# define RTSemMutexRequestNoResume(pCritSect, cMillies) RTSemMutexRequestNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
464# else
465# define RTSemMutexRequest(pCritSect, cMillies) RTSemMutexRequestDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
466# define RTSemMutexRequestNoResume(pCritSect, cMillies) RTSemMutexRequestNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
467# endif
468#endif
469
470/** @} */
471
472
473/** @defgroup grp_rt_sems_fast_mutex RTSemFastMutex - Fast Mutex Semaphores
474 *
475 * Fast mutexes work like regular mutexes in that they allow only a single
476 * thread access to a critical piece of code or data. As opposed to mutexes,
477 * they require no syscall if the fast mutex is not held (like critical
478 * sections). Unlike critical sections however, they are *not* recursive.
479 *
480 * @{ */
481
482/**
483 * Create a fast mutex semaphore.
484 *
485 * @returns iprt status code.
486 * @param phFastMtx Where to store the handle to the newly created
487 * fast mutex semaphore.
488 *
489 * @remarks Fast mutex semaphores are not recursive.
490 */
491RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx);
492
493/**
494 * Destroy a fast mutex semaphore.
495 *
496 * @returns iprt status code.
497 * @param hFastMtx Handle to the fast mutex semaphore. NIL is
498 * quietly ignored (VINF_SUCCESS).
499 */
500RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx);
501
502/**
503 * Request ownership of a fast mutex semaphore.
504 *
505 * The same thread may request a mutex semaphore multiple times,
506 * a nested counter is kept to make sure it's released on the right
507 * RTSemMutexRelease() call.
508 *
509 * @returns iprt status code.
510 * @param hFastMtx Handle to the fast mutex semaphore.
511 */
512RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx);
513
514/**
515 * Release the ownership of a fast mutex semaphore.
516 *
517 * @returns iprt status code.
518 * @param hFastMtx Handle to the fast mutex semaphore. It goes
519 * without saying the the calling thread must own
520 * it.
521 */
522RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx);
523
524/** @} */
525
526
527/** @defgroup grp_rt_sems_spin_mutex RTSemSpinMutex - Spinning Mutex Semaphores
528 *
529 * A very adaptive variant of mutex semaphore that is tailored for the ring-0
530 * logger.
531 *
532 * @{ */
533
534/**
535 * Creates a spinning mutex semaphore.
536 *
537 * @returns iprt status code.
538 * @retval VERR_INVALID_PARAMETER on invalid flags.
539 * @retval VERR_NO_MEMORY if out of memory for the semaphore structure and
540 * handle.
541 *
542 * @param phSpinMtx Where to return the handle to the create semaphore.
543 * @param fFlags Flags, see RTSEMSPINMUTEX_FLAGS_XXX.
544 */
545RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags);
546
547/** @name RTSemSpinMutexCreate flags.
548 * @{ */
549/** Always take the semaphore in a IRQ safe way.
550 * (In plain words: always disable interrupts.) */
551#define RTSEMSPINMUTEX_FLAGS_IRQ_SAFE RT_BIT_32(0)
552/** Mask of valid flags. */
553#define RTSEMSPINMUTEX_FLAGS_VALID_MASK UINT32_C(0x00000001)
554/** @} */
555
556/**
557 * Destroys a spinning mutex semaphore.
558 *
559 * @returns iprt status code.
560 * @retval VERR_INVALID_HANDLE (or crash) if the handle is invalid. (NIL will
561 * not cause this status.)
562 *
563 * @param hSpinMtx The semaphore handle. NIL_RTSEMSPINMUTEX is ignored
564 * quietly (VINF_SUCCESS).
565 */
566RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx);
567
568/**
569 * Request the spinning mutex semaphore.
570 *
571 * This may block if the context we're called in allows this. If not it will
572 * spin. If called in an interrupt context, we will only spin if the current
573 * owner isn't interrupted. Also, on some systems it is not always possible to
574 * wake up blocking threads in all contexts, so, which will either be indicated
575 * by returning VERR_SEM_BAD_CONTEXT or by temporarily switching the semaphore
576 * into pure spinlock state.
577 *
578 * Preemption will be disabled upon return. IRQs may also be disabled.
579 *
580 * @returns iprt status code.
581 * @retval VERR_SEM_BAD_CONTEXT if the context it's called in isn't suitable
582 * for releasing it if someone is sleeping on it.
583 * @retval VERR_SEM_DESTROYED if destroyed.
584 * @retval VERR_SEM_NESTED if held by the caller. Asserted.
585 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted
586 *
587 * @param hSpinMtx The semaphore handle.
588 */
589RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx);
590
591/**
592 * Like RTSemSpinMutexRequest but it won't block or spin if the semaphore is
593 * held by someone else.
594 *
595 * @returns iprt status code.
596 * @retval VERR_SEM_BUSY if held by someone else.
597 * @retval VERR_SEM_DESTROYED if destroyed.
598 * @retval VERR_SEM_NESTED if held by the caller. Asserted.
599 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted
600 *
601 * @param hSpinMtx The semaphore handle.
602 */
603RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx);
604
605/**
606 * Releases the semaphore previously acquired by RTSemSpinMutexRequest or
607 * RTSemSpinMutexTryRequest.
608 *
609 * @returns iprt status code.
610 * @retval VERR_SEM_DESTROYED if destroyed.
611 * @retval VERR_NOT_OWNER if not owner. Asserted.
612 * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted.
613 *
614 * @param hSpinMtx The semaphore handle.
615 */
616RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx);
617
618/** @} */
619
620
621/** @defgroup grp_rt_sem_rw RTSemRW - Read / Write Semaphores
622 *
623 * Read/write semaphores are a fancier version of mutexes in that they grant
624 * read access to the protected data to several threads at the same time but
625 * allow only one writer at a time. This can make code scale better at the
626 * expense of slightly more overhead in mutex management.
627 *
628 * @{ */
629
630/**
631 * Creates a read/write semaphore.
632 *
633 * @returns iprt status code.
634 * @param phRWSem Where to store the handle to the newly created
635 * RW semaphore.
636 */
637RTDECL(int) RTSemRWCreate(PRTSEMRW phRWSem);
638
639/**
640 * Creates a read/write semaphore.
641 *
642 * @returns iprt status code.
643 * @param phRWSem Where to store the handle to the newly created
644 * RW semaphore.
645 * @param fFlags Flags, any combination of the RTSEMRW_FLAGS_XXX
646 * \#defines.
647 * @param hClass The class (no reference consumed). If NIL, no
648 * lock order validation will be performed on this
649 * lock.
650 * @param uSubClass The sub-class. This is used to define lock
651 * order within a class. RTLOCKVAL_SUB_CLASS_NONE
652 * is the recommended value here.
653 * @param pszNameFmt Name format string for the lock validator,
654 * optional (NULL). Max length is 32 bytes.
655 * @param ... Format string arguments.
656 */
657RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags,
658 RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...);
659
660/** @name RTSemRWCreateEx flags
661 * @{ */
662/** Disables lock validation. */
663#define RTSEMRW_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
664/** @} */
665
666/**
667 * Destroys a read/write semaphore.
668 *
669 * @returns iprt status code.
670 * @param hRWSem Handle to the read/write semaphore. NIL is
671 * quitly ignored (VINF_SUCCESS).
672 */
673RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem);
674
675/**
676 * Changes the lock validator sub-class of the read/write semaphore.
677 *
678 * It is recommended to try make sure that nobody is using this sempahore while
679 * changing the value.
680 *
681 * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the
682 * lock validator isn't compiled in or either of the parameters are
683 * invalid.
684 * @param hRWSem Handle to the read/write semaphore.
685 * @param uSubClass The new sub-class value.
686 */
687RTDECL(uint32_t) RTSemRWSetSubClass(RTSEMRW hRWSem, uint32_t uSubClass);
688
689/**
690 * Request read access to a read/write semaphore, resume on interruption
691 *
692 * @returns iprt status code.
693 * @retval VINF_SUCCESS on success.
694 * @retval VERR_INTERRUPT if the wait was interrupted.
695 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
696 *
697 * @param hRWSem Handle to the read/write semaphore.
698 * @param cMillies The number of milliseconds to wait.
699 */
700RTDECL(int) RTSemRWRequestRead(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
701
702/**
703 * Request read access to a read/write semaphore, return on interruption
704 *
705 * @returns iprt status code.
706 * @retval VINF_SUCCESS on success.
707 * @retval VERR_INTERRUPT if the wait was interrupted.
708 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
709 *
710 * @param hRWSem Handle to the read/write semaphore.
711 * @param cMillies The number of milliseconds to wait.
712 */
713RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
714
715/**
716 * Debug version of RTSemRWRequestRead that tracks the location.
717 *
718 * @returns iprt status code.
719 * @retval VINF_SUCCESS on success.
720 * @retval VERR_INTERRUPT if the wait was interrupted.
721 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
722 *
723 * @param hRWSem Handle to the read/write semaphore.
724 * @param cMillies The number of milliseconds to wait.
725 * @param uId Some kind of locking location ID. Typically a
726 * return address up the stack. Optional (0).
727 * @param pszFile The file where the lock is being acquired from.
728 * Optional.
729 * @param iLine The line number in that file. Optional (0).
730 * @param pszFunction The functionn where the lock is being acquired
731 * from. Optional.
732 */
733RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
734
735/**
736 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
737 *
738 * @returns iprt status code.
739 * @retval VINF_SUCCESS on success.
740 * @retval VERR_INTERRUPT if the wait was interrupted.
741 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
742 *
743 * @param hRWSem Handle to the read/write semaphore.
744 * @param cMillies The number of milliseconds to wait.
745 * @param uId Some kind of locking location ID. Typically a
746 * return address up the stack. Optional (0).
747 * @param pszFile The file where the lock is being acquired from.
748 * Optional.
749 * @param iLine The line number in that file. Optional (0).
750 * @param pszFunction The functionn where the lock is being acquired
751 * from. Optional.
752 */
753RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
754
755/**
756 * Release read access to a read/write semaphore.
757 *
758 * @returns iprt status code.
759 * @param hRWSem Handle to the read/write semaphore. It goes
760 * without saying that caller must own read
761 * privileges to the semaphore.
762 */
763RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem);
764
765/**
766 * Request write access to a read/write semaphore, resume on interruption.
767 *
768 * @returns iprt status code.
769 * @retval VINF_SUCCESS on success.
770 * @retval VERR_DEADLOCK if the caller owned the read lock.
771 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
772 *
773 * @param hRWSem Handle to the read/write semaphore.
774 * @param cMillies The number of milliseconds to wait.
775 */
776RTDECL(int) RTSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
777
778/**
779 * Request write access to a read/write semaphore, return on interruption.
780 *
781 * @returns iprt status code.
782 * @retval VINF_SUCCESS on success.
783 * @retval VERR_INTERRUPT if the wait was interrupted.
784 * @retval VERR_DEADLOCK if the caller owned the read lock.
785 * @retval VERR_INVALID_HANDLE if hRWSem is invalid.
786 *
787 * @param hRWSem Handle to the read/write semaphore.
788 * @param cMillies The number of milliseconds to wait.
789 */
790RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies);
791
792/**
793 * Debug version of RTSemRWRequestWrite that tracks the location.
794 *
795 * @returns IPRT status code, see RTSemRWRequestWrite.
796 * @param hRWSem Handle to the read/write semaphore.
797 * @param cMillies The number of milliseconds to wait.
798 * @param uId Some kind of locking location ID. Typically a
799 * return address up the stack. Optional (0).
800 * @param pszFile The file where the lock is being acquired from.
801 * Optional.
802 * @param iLine The line number in that file. Optional (0).
803 * @param pszFunction The functionn where the lock is being acquired
804 * from. Optional.
805 */
806RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
807
808/**
809 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
810 *
811 * @returns IPRT status code, see RTSemRWRequestWriteNoResume.
812 * @param hRWSem Handle to the read/write semaphore.
813 * @param cMillies The number of milliseconds to wait.
814 * @param uId Some kind of locking location ID. Typically a
815 * return address up the stack. Optional (0).
816 * @param pszFile The file where the lock is being acquired from.
817 * Optional.
818 * @param iLine The line number in that file. Optional (0).
819 * @param pszFunction The functionn where the lock is being acquired
820 * from. Optional.
821 */
822RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
823
824/**
825 * Release write access to a read/write semaphore.
826 *
827 * @returns iprt status code.
828 * @param hRWSem Handle to the read/write semaphore. Goes
829 * without saying that caller must have write
830 * access to the semaphore.
831 */
832RTDECL(int) RTSemRWReleaseWrite(RTSEMRW hRWSem);
833
834/**
835 * Checks if the caller is the exclusive semaphore owner.
836 *
837 * @returns true / false accoringly.
838 * @param hRWSem Handle to the read/write semaphore.
839 */
840RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW hRWSem);
841
842/**
843 * Gets the write recursion count.
844 *
845 * @returns The write recursion count (0 if bad semaphore handle).
846 * @param hRWSem Handle to the read/write semaphore.
847 */
848RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem);
849
850/**
851 * Gets the read recursion count of the current writer.
852 *
853 * @returns The read recursion count (0 if bad semaphore handle).
854 * @param hRWSem Handle to the read/write semaphore.
855 */
856RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem);
857
858/**
859 * Gets the current number of reads.
860 *
861 * This includes all read recursions, so it might be higher than the number of
862 * read owners. It does not include reads done by the current writer.
863 *
864 * @returns The read count (0 if bad semaphore handle).
865 * @param hRWSem Handle to the read/write semaphore.
866 */
867RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem);
868
869/* Strict build: Remap the four request calls to the debug versions. */
870#ifdef RT_STRICT
871# ifdef ___iprt_asm_h
872# define RTSemRWRequestRead(pCritSect, cMillies) RTSemRWRequestReadDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
873# define RTSemRWRequestReadNoResume(pCritSect, cMillies) RTSemRWRequestReadNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
874# define RTSemRWRequestWrite(pCritSect, cMillies) RTSemRWRequestWriteDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
875# define RTSemRWRequestWriteNoResume(pCritSect, cMillies) RTSemRWRequestWriteNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
876# else
877# define RTSemRWRequestRead(pCritSect, cMillies) RTSemRWRequestReadDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
878# define RTSemRWRequestReadNoResume(pCritSect, cMillies) RTSemRWRequestReadNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
879# define RTSemRWRequestWrite(pCritSect, cMillies) RTSemRWRequestWriteDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
880# define RTSemRWRequestWriteNoResume(pCritSect, cMillies) RTSemRWRequestWriteNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
881# endif
882#endif
883
884/** @} */
885
886
887/** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct
888 *
889 * Serialization of a two way communication.
890 *
891 * @{ */
892
893/**
894 * Ping-pong speaker
895 */
896typedef enum RTPINGPONGSPEAKER
897{
898 /** Not initialized. */
899 RTPINGPONGSPEAKER_UNINITIALIZE = 0,
900 /** Ping is speaking, Pong is waiting. */
901 RTPINGPONGSPEAKER_PING,
902 /** Pong is signaled, Ping is waiting. */
903 RTPINGPONGSPEAKER_PONG_SIGNALED,
904 /** Pong is speaking, Ping is waiting. */
905 RTPINGPONGSPEAKER_PONG,
906 /** Ping is signaled, Pong is waiting. */
907 RTPINGPONGSPEAKER_PING_SIGNALED,
908 /** Hack to ensure that it's at least 32-bits wide. */
909 RTPINGPONGSPEAKER_HACK = 0x7fffffff
910} RTPINGPONGSPEAKER;
911
912/**
913 * Ping-Pong construct.
914 *
915 * Two threads, one saying Ping and the other saying Pong. The construct
916 * makes sure they don't speak out of turn and that they can wait and poll
917 * on the conversation.
918 */
919typedef struct RTPINGPONG
920{
921 /** The semaphore the Ping thread waits on. */
922 RTSEMEVENT Ping;
923 /** The semaphore the Pong thread waits on. */
924 RTSEMEVENT Pong;
925 /** The current speaker. */
926 volatile RTPINGPONGSPEAKER enmSpeaker;
927#if HC_ARCH_BITS == 64
928 /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
929 uint32_t u32Padding;
930#endif
931} RTPINGPONG;
932/** Pointer to Ping-Pong construct. */
933typedef RTPINGPONG *PRTPINGPONG;
934
935/**
936 * Init a Ping-Pong construct.
937 *
938 * @returns iprt status code.
939 * @param pPP Pointer to the ping-pong structure which needs initialization.
940 */
941RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
942
943/**
944 * Deletes a Ping-Pong construct.
945 *
946 * @returns iprt status code.
947 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
948 * (I.e. put into uninitialized state.)
949 */
950RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
951
952/**
953 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
954 * This is called by the ping thread.
955 *
956 * @returns iprt status code.
957 * @param pPP Pointer to the ping-pong structure to ping.
958 */
959RTDECL(int) RTSemPing(PRTPINGPONG pPP);
960
961/**
962 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
963 * This is called by the pong thread.
964 *
965 * @returns iprt status code.
966 * @param pPP Pointer to the ping-pong structure to pong.
967 */
968RTDECL(int) RTSemPong(PRTPINGPONG pPP);
969
970/**
971 * Wait function for the ping thread.
972 *
973 * @returns iprt status code.
974 * Will not return VERR_INTERRUPTED.
975 * @param pPP Pointer to the ping-pong structure to wait on.
976 * @param cMillies Number of milliseconds to wait.
977 */
978RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
979
980/**
981 * Wait function for the pong thread.
982 *
983 * @returns iprt status code.
984 * Will not return VERR_INTERRUPTED.
985 * @param pPP Pointer to the ping-pong structure to wait on.
986 * @param cMillies Number of milliseconds to wait.
987 */
988RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
989
990
991/**
992 * Checks if the pong thread is speaking.
993 *
994 * @returns true / false.
995 * @param pPP Pointer to the ping-pong structure.
996 * @remark This is NOT the same as !RTSemPongIsSpeaker().
997 */
998DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
999{
1000 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1001 return enmSpeaker == RTPINGPONGSPEAKER_PING;
1002}
1003
1004
1005/**
1006 * Checks if the pong thread is speaking.
1007 *
1008 * @returns true / false.
1009 * @param pPP Pointer to the ping-pong structure.
1010 * @remark This is NOT the same as !RTSemPingIsSpeaker().
1011 */
1012DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
1013{
1014 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1015 return enmSpeaker == RTPINGPONGSPEAKER_PONG;
1016}
1017
1018
1019/**
1020 * Checks whether the ping thread should wait.
1021 *
1022 * @returns true / false.
1023 * @param pPP Pointer to the ping-pong structure.
1024 * @remark This is NOT the same as !RTSemPongShouldWait().
1025 */
1026DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
1027{
1028 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1029 return enmSpeaker == RTPINGPONGSPEAKER_PONG
1030 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
1031 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
1032}
1033
1034
1035/**
1036 * Checks whether the pong thread should wait.
1037 *
1038 * @returns true / false.
1039 * @param pPP Pointer to the ping-pong structure.
1040 * @remark This is NOT the same as !RTSemPingShouldWait().
1041 */
1042DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
1043{
1044 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1045 return enmSpeaker == RTPINGPONGSPEAKER_PING
1046 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
1047 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
1048}
1049
1050/** @} */
1051
1052
1053/** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads
1054 *
1055 * The crossroads semaphore is intended to prevent two classes of incompatible
1056 * events from occuring simultaneously, like south/north bound traffic and
1057 * west/east bound traffic at a 4-way junction.
1058 *
1059 * @remarks In order to simplify the implementation, the current flow is always
1060 * given priority. So, it won't work at all well when busy!
1061 *
1062 * @remarks "XRoads" is used as a name because it is briefer than "crossroads"
1063 * and it slightly stresses that is a 4 way crossing to the users of
1064 * American English.
1065 * @{
1066 */
1067
1068/**
1069 * Creates a crossroads semaphore.
1070 *
1071 * @returns IPRT status code.
1072 *
1073 * @param phXRoads Where to return the handle to the newly created
1074 * crossroads semaphore.
1075 */
1076RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads);
1077
1078/**
1079 * Destroys a crossroads semaphore.
1080 *
1081 * @returns IPRT status code.
1082 *
1083 * @param hXRoads Handle to the crossroads semaphore that is to be
1084 * destroyed. NIL_RTSEMXROADS is quitetly ignored
1085 * (VINF_SUCCESS).
1086 */
1087RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads);
1088
1089/**
1090 * Enter the crossroads from the south or north.
1091 *
1092 * (Coupled with RTSemXRoadsNSLeave.)
1093 *
1094 * @returns IPRT status code.
1095 * @param hXRoads Handle to the crossroads semaphore.
1096 */
1097RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads);
1098
1099/**
1100 * Leave the crossroads to the north or south.
1101 *
1102 * (Coupled with RTSemXRoadsNSEnter.)
1103 *
1104 * @returns IPRT status code.
1105 * @param hXRoads Handle to the crossroads semaphore.
1106 */
1107RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads);
1108
1109/**
1110 * Leave the crossroads from the east or west.
1111 *
1112 * (Coupled with RTSemXRoadsEWLeave.)
1113 *
1114 * @returns IPRT status code.
1115 * @param hXRoads Handle to the crossroads semaphore.
1116 */
1117RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads);
1118
1119/**
1120 * Leave the crossroads to the west or east.
1121 *
1122 * (Coupled with RTSemXRoadsEWEnter.)
1123 *
1124 * @returns IPRT status code.
1125 * @param hXRoads Handle to the crossroads semaphore.
1126 */
1127RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads);
1128
1129/** @} */
1130
1131/** @} */
1132
1133RT_C_DECLS_END
1134
1135#endif
1136
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