VirtualBox

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

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

RTSemRWIsReadOwner: For assertion in main.

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