VirtualBox

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

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

iprt/semaphore.h: RT_LOCK_CHECK_ORDER && IN_RING3 -> wrap RTSemRWCreate and RTSemMutexCreate so automatic order validation is performed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.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 * Gets the write recursion count.
855 *
856 * @returns The write recursion count (0 if bad semaphore handle).
857 * @param hRWSem Handle to the read/write semaphore.
858 */
859RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem);
860
861/**
862 * Gets the read recursion count of the current writer.
863 *
864 * @returns The read recursion count (0 if bad semaphore handle).
865 * @param hRWSem Handle to the read/write semaphore.
866 */
867RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem);
868
869/**
870 * Gets the current number of reads.
871 *
872 * This includes all read recursions, so it might be higher than the number of
873 * read owners. It does not include reads done by the current writer.
874 *
875 * @returns The read count (0 if bad semaphore handle).
876 * @param hRWSem Handle to the read/write semaphore.
877 */
878RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem);
879
880/* Strict build: Remap the four request calls to the debug versions. */
881#ifdef RT_STRICT
882# ifdef ___iprt_asm_h
883# define RTSemRWRequestRead(pCritSect, cMillies) RTSemRWRequestReadDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
884# define RTSemRWRequestReadNoResume(pCritSect, cMillies) RTSemRWRequestReadNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
885# define RTSemRWRequestWrite(pCritSect, cMillies) RTSemRWRequestWriteDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
886# define RTSemRWRequestWriteNoResume(pCritSect, cMillies) RTSemRWRequestWriteNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
887# else
888# define RTSemRWRequestRead(pCritSect, cMillies) RTSemRWRequestReadDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
889# define RTSemRWRequestReadNoResume(pCritSect, cMillies) RTSemRWRequestReadNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
890# define RTSemRWRequestWrite(pCritSect, cMillies) RTSemRWRequestWriteDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
891# define RTSemRWRequestWriteNoResume(pCritSect, cMillies) RTSemRWRequestWriteNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
892# endif
893#endif
894
895/* Strict lock order: Automatically classify locks by init location. */
896#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3)
897# define RTSemRWCreate(phSemRW) \
898 RTSemRWCreateEx((phSemRW), 0 /*fFlags*/, \
899 RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
900 RTLOCKVAL_SUB_CLASS_NONE, NULL)
901#endif
902
903/** @} */
904
905
906/** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct
907 *
908 * Serialization of a two way communication.
909 *
910 * @{ */
911
912/**
913 * Ping-pong speaker
914 */
915typedef enum RTPINGPONGSPEAKER
916{
917 /** Not initialized. */
918 RTPINGPONGSPEAKER_UNINITIALIZE = 0,
919 /** Ping is speaking, Pong is waiting. */
920 RTPINGPONGSPEAKER_PING,
921 /** Pong is signaled, Ping is waiting. */
922 RTPINGPONGSPEAKER_PONG_SIGNALED,
923 /** Pong is speaking, Ping is waiting. */
924 RTPINGPONGSPEAKER_PONG,
925 /** Ping is signaled, Pong is waiting. */
926 RTPINGPONGSPEAKER_PING_SIGNALED,
927 /** Hack to ensure that it's at least 32-bits wide. */
928 RTPINGPONGSPEAKER_HACK = 0x7fffffff
929} RTPINGPONGSPEAKER;
930
931/**
932 * Ping-Pong construct.
933 *
934 * Two threads, one saying Ping and the other saying Pong. The construct
935 * makes sure they don't speak out of turn and that they can wait and poll
936 * on the conversation.
937 */
938typedef struct RTPINGPONG
939{
940 /** The semaphore the Ping thread waits on. */
941 RTSEMEVENT Ping;
942 /** The semaphore the Pong thread waits on. */
943 RTSEMEVENT Pong;
944 /** The current speaker. */
945 volatile RTPINGPONGSPEAKER enmSpeaker;
946#if HC_ARCH_BITS == 64
947 /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
948 uint32_t u32Padding;
949#endif
950} RTPINGPONG;
951/** Pointer to Ping-Pong construct. */
952typedef RTPINGPONG *PRTPINGPONG;
953
954/**
955 * Init a Ping-Pong construct.
956 *
957 * @returns iprt status code.
958 * @param pPP Pointer to the ping-pong structure which needs initialization.
959 */
960RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
961
962/**
963 * Deletes a Ping-Pong construct.
964 *
965 * @returns iprt status code.
966 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
967 * (I.e. put into uninitialized state.)
968 */
969RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
970
971/**
972 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
973 * This is called by the ping thread.
974 *
975 * @returns iprt status code.
976 * @param pPP Pointer to the ping-pong structure to ping.
977 */
978RTDECL(int) RTSemPing(PRTPINGPONG pPP);
979
980/**
981 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
982 * This is called by the pong thread.
983 *
984 * @returns iprt status code.
985 * @param pPP Pointer to the ping-pong structure to pong.
986 */
987RTDECL(int) RTSemPong(PRTPINGPONG pPP);
988
989/**
990 * Wait function for the ping thread.
991 *
992 * @returns iprt status code.
993 * Will not return VERR_INTERRUPTED.
994 * @param pPP Pointer to the ping-pong structure to wait on.
995 * @param cMillies Number of milliseconds to wait.
996 */
997RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
998
999/**
1000 * Wait function for the pong thread.
1001 *
1002 * @returns iprt status code.
1003 * Will not return VERR_INTERRUPTED.
1004 * @param pPP Pointer to the ping-pong structure to wait on.
1005 * @param cMillies Number of milliseconds to wait.
1006 */
1007RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies);
1008
1009
1010/**
1011 * Checks if the pong thread is speaking.
1012 *
1013 * @returns true / false.
1014 * @param pPP Pointer to the ping-pong structure.
1015 * @remark This is NOT the same as !RTSemPongIsSpeaker().
1016 */
1017DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
1018{
1019 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1020 return enmSpeaker == RTPINGPONGSPEAKER_PING;
1021}
1022
1023
1024/**
1025 * Checks if the pong thread is speaking.
1026 *
1027 * @returns true / false.
1028 * @param pPP Pointer to the ping-pong structure.
1029 * @remark This is NOT the same as !RTSemPingIsSpeaker().
1030 */
1031DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
1032{
1033 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1034 return enmSpeaker == RTPINGPONGSPEAKER_PONG;
1035}
1036
1037
1038/**
1039 * Checks whether the ping thread should wait.
1040 *
1041 * @returns true / false.
1042 * @param pPP Pointer to the ping-pong structure.
1043 * @remark This is NOT the same as !RTSemPongShouldWait().
1044 */
1045DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
1046{
1047 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1048 return enmSpeaker == RTPINGPONGSPEAKER_PONG
1049 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
1050 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
1051}
1052
1053
1054/**
1055 * Checks whether the pong thread should wait.
1056 *
1057 * @returns true / false.
1058 * @param pPP Pointer to the ping-pong structure.
1059 * @remark This is NOT the same as !RTSemPingShouldWait().
1060 */
1061DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
1062{
1063 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
1064 return enmSpeaker == RTPINGPONGSPEAKER_PING
1065 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
1066 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
1067}
1068
1069/** @} */
1070
1071
1072/** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads
1073 *
1074 * The crossroads semaphore is intended to prevent two classes of incompatible
1075 * events from occuring simultaneously, like south/north bound traffic and
1076 * west/east bound traffic at a 4-way junction.
1077 *
1078 * @remarks In order to simplify the implementation, the current flow is always
1079 * given priority. So, it won't work at all well when busy!
1080 *
1081 * @remarks "XRoads" is used as a name because it is briefer than "crossroads"
1082 * and it slightly stresses that is a 4 way crossing to the users of
1083 * American English.
1084 * @{
1085 */
1086
1087/**
1088 * Creates a crossroads semaphore.
1089 *
1090 * @returns IPRT status code.
1091 *
1092 * @param phXRoads Where to return the handle to the newly created
1093 * crossroads semaphore.
1094 */
1095RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads);
1096
1097/**
1098 * Destroys a crossroads semaphore.
1099 *
1100 * @returns IPRT status code.
1101 *
1102 * @param hXRoads Handle to the crossroads semaphore that is to be
1103 * destroyed. NIL_RTSEMXROADS is quitetly ignored
1104 * (VINF_SUCCESS).
1105 */
1106RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads);
1107
1108/**
1109 * Enter the crossroads from the south or north.
1110 *
1111 * (Coupled with RTSemXRoadsNSLeave.)
1112 *
1113 * @returns IPRT status code.
1114 * @param hXRoads Handle to the crossroads semaphore.
1115 */
1116RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads);
1117
1118/**
1119 * Leave the crossroads to the north or south.
1120 *
1121 * (Coupled with RTSemXRoadsNSEnter.)
1122 *
1123 * @returns IPRT status code.
1124 * @param hXRoads Handle to the crossroads semaphore.
1125 */
1126RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads);
1127
1128/**
1129 * Leave the crossroads from the east or west.
1130 *
1131 * (Coupled with RTSemXRoadsEWLeave.)
1132 *
1133 * @returns IPRT status code.
1134 * @param hXRoads Handle to the crossroads semaphore.
1135 */
1136RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads);
1137
1138/**
1139 * Leave the crossroads to the west or east.
1140 *
1141 * (Coupled with RTSemXRoadsEWEnter.)
1142 *
1143 * @returns IPRT status code.
1144 * @param hXRoads Handle to the crossroads semaphore.
1145 */
1146RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads);
1147
1148/** @} */
1149
1150/** @} */
1151
1152RT_C_DECLS_END
1153
1154#endif
1155
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