VirtualBox

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

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

iprt: Added RTSemRWCreateEx and RTSemRWSetSubClass. Updated tstRTLockValidator with a test of the SemRW lock order validation.

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