VirtualBox

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

Last change on this file since 31155 was 31155, checked in by vboxsync, 14 years ago

iprt/condvar.h: condition variable spec.

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