VirtualBox

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

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

IPRT,DoxyFile.Core: Mopped up the errors in the IPRT doxygen run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.8 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 pRWSem Where to store the handle to the created RW semaphore.
535 */
536RTDECL(int) RTSemRWCreate(PRTSEMRW pRWSem);
537
538/**
539 * Destroys a read/write semaphore.
540 *
541 * @returns iprt status code.
542 * @param RWSem The Read/Write semaphore to destroy.
543 */
544RTDECL(int) RTSemRWDestroy(RTSEMRW RWSem);
545
546/**
547 * Request read access to a read/write semaphore, resume on interruption
548 *
549 * @returns iprt status code.
550 * @retval VINF_SUCCESS on success.
551 * @retval VERR_INTERRUPT if the wait was interrupted.
552 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
553 *
554 * @param RWSem The Read/Write semaphore to request read access to.
555 * @param cMillies The number of milliseconds to wait.
556 */
557RTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies);
558
559/**
560 * Request read access to a read/write semaphore, return on interruption
561 *
562 * @returns iprt status code.
563 * @retval VINF_SUCCESS on success.
564 * @retval VERR_INTERRUPT if the wait was interrupted.
565 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
566 *
567 * @param RWSem The Read/Write semaphore to request read access to.
568 * @param cMillies The number of milliseconds to wait.
569 */
570RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies);
571
572/**
573 * Debug version of RTSemRWRequestRead that tracks the location.
574 *
575 * @returns iprt status code.
576 * @retval VINF_SUCCESS on success.
577 * @retval VERR_INTERRUPT if the wait was interrupted.
578 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
579 *
580 * @param RWSem The Read/Write semaphore to request read access to.
581 * @param cMillies The number of milliseconds to wait.
582 * @param uId Some kind of locking location ID. Typically a
583 * return address up the stack. Optional (0).
584 * @param pszFile The file where the lock is being acquired from.
585 * Optional.
586 * @param iLine The line number in that file. Optional (0).
587 * @param pszFunction The functionn where the lock is being acquired
588 * from. Optional.
589 */
590RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
591
592/**
593 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
594 *
595 * @returns iprt status code.
596 * @retval VINF_SUCCESS on success.
597 * @retval VERR_INTERRUPT if the wait was interrupted.
598 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
599 *
600 * @param RWSem The Read/Write semaphore to request read access to.
601 * @param cMillies The number of milliseconds to wait.
602 * @param uId Some kind of locking location ID. Typically a
603 * return address up the stack. Optional (0).
604 * @param pszFile The file where the lock is being acquired from.
605 * Optional.
606 * @param iLine The line number in that file. Optional (0).
607 * @param pszFunction The functionn where the lock is being acquired
608 * from. Optional.
609 */
610RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
611
612/**
613 * Release read access to a read/write semaphore.
614 *
615 * @returns iprt status code.
616 * @param RWSem The Read/Write sempahore to release read access to.
617 * Goes without saying that caller must have read access to the sem.
618 */
619RTDECL(int) RTSemRWReleaseRead(RTSEMRW RWSem);
620
621/**
622 * Request write access to a read/write semaphore, resume on interruption.
623 *
624 * @returns iprt status code.
625 * @retval VINF_SUCCESS on success.
626 * @retval VERR_DEADLOCK if the caller owned the read lock.
627 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
628 *
629 * @param RWSem The Read/Write semaphore to request write access to.
630 * @param cMillies The number of milliseconds to wait.
631 */
632RTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies);
633
634/**
635 * Request write access to a read/write semaphore, return on interruption.
636 *
637 * @returns iprt status code.
638 * @retval VINF_SUCCESS on success.
639 * @retval VERR_INTERRUPT if the wait was interrupted.
640 * @retval VERR_DEADLOCK if the caller owned the read lock.
641 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
642 *
643 * @param RWSem The Read/Write semaphore to request write access to.
644 * @param cMillies The number of milliseconds to wait.
645 */
646RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies);
647
648/**
649 * Debug version of RTSemRWRequestWrite that tracks the location.
650 *
651 * @returns IPRT status code, see RTSemRWRequestWrite.
652 * @param RWSem The Read/Write semaphore to request write access
653 * to.
654 * @param cMillies The number of milliseconds to wait.
655 * @param uId Some kind of locking location ID. Typically a
656 * return address up the stack. Optional (0).
657 * @param pszFile The file where the lock is being acquired from.
658 * Optional.
659 * @param iLine The line number in that file. Optional (0).
660 * @param pszFunction The functionn where the lock is being acquired
661 * from. Optional.
662 */
663RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
664
665/**
666 * Debug version of RTSemRWRequestWriteNoResume that tracks the location.
667 *
668 * @returns IPRT status code, see RTSemRWRequestWriteNoResume.
669 * @param RWSem The Read/Write semaphore to request write access
670 * to.
671 * @param cMillies The number of milliseconds to wait.
672 * @param uId Some kind of locking location ID. Typically a
673 * return address up the stack. Optional (0).
674 * @param pszFile The file where the lock is being acquired from.
675 * Optional.
676 * @param iLine The line number in that file. Optional (0).
677 * @param pszFunction The functionn where the lock is being acquired
678 * from. Optional.
679 */
680RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL);
681
682/**
683 * Release write access to a read/write semaphore.
684 *
685 * @returns iprt status code.
686 * @param RWSem The Read/Write sempahore to release read access to.
687 * Goes without saying that caller must have write access to the sem.
688 */
689RTDECL(int) RTSemRWReleaseWrite(RTSEMRW RWSem);
690
691/**
692 * Checks if the caller is the exclusive semaphore owner.
693 *
694 * @returns true / false accoringly.
695 * @param RWSem The Read/Write semaphore in question.
696 */
697RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW RWSem);
698
699/**
700 * Gets the write recursion count.
701 *
702 * @returns The write recursion count (0 if bad semaphore handle).
703 * @param RWSem The Read/Write semaphore in question.
704 */
705RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW RWSem);
706
707/**
708 * Gets the read recursion count of the current writer.
709 *
710 * @returns The read recursion count (0 if bad semaphore handle).
711 * @param RWSem The Read/Write semaphore in question.
712 */
713RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW RWSem);
714
715/**
716 * Gets the current number of reads.
717 *
718 * This includes all read recursions, so it might be higher than the number of
719 * read owners. It does not include reads done by the current writer.
720 *
721 * @returns The read count (0 if bad semaphore handle).
722 * @param RWSem The Read/Write semaphore in question.
723 */
724RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW RWSem);
725
726/* Strict build: Remap the four request calls to the debug versions. */
727#ifdef RT_STRICT
728# ifdef ___iprt_asm_h
729# define RTSemRWRequestRead(pCritSect, cMillies) RTSemRWRequestReadDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
730# define RTSemRWRequestReadNoResume(pCritSect, cMillies) RTSemRWRequestReadNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
731# define RTSemRWRequestWrite(pCritSect, cMillies) RTSemRWRequestWriteDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
732# define RTSemRWRequestWriteNoResume(pCritSect, cMillies) RTSemRWRequestWriteNoResumeDebug((pCritSect), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
733# else
734# define RTSemRWRequestRead(pCritSect, cMillies) RTSemRWRequestReadDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
735# define RTSemRWRequestReadNoResume(pCritSect, cMillies) RTSemRWRequestReadNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
736# define RTSemRWRequestWrite(pCritSect, cMillies) RTSemRWRequestWriteDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
737# define RTSemRWRequestWriteNoResume(pCritSect, cMillies) RTSemRWRequestWriteNoResumeDebug((pCritSect), (cMillies), 0, RT_SRC_POS)
738# endif
739#endif
740
741/** @} */
742
743
744/** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct
745 *
746 * Serialization of a two way communication.
747 *
748 * @{ */
749
750/**
751 * Ping-pong speaker
752 */
753typedef enum RTPINGPONGSPEAKER
754{
755 /** Not initialized. */
756 RTPINGPONGSPEAKER_UNINITIALIZE = 0,
757 /** Ping is speaking, Pong is waiting. */
758 RTPINGPONGSPEAKER_PING,
759 /** Pong is signaled, Ping is waiting. */
760 RTPINGPONGSPEAKER_PONG_SIGNALED,
761 /** Pong is speaking, Ping is waiting. */
762 RTPINGPONGSPEAKER_PONG,
763 /** Ping is signaled, Pong is waiting. */
764 RTPINGPONGSPEAKER_PING_SIGNALED,
765 /** Hack to ensure that it's at least 32-bits wide. */
766 RTPINGPONGSPEAKER_HACK = 0x7fffffff
767} RTPINGPONGSPEAKER;
768
769/**
770 * Ping-Pong construct.
771 *
772 * Two threads, one saying Ping and the other saying Pong. The construct
773 * makes sure they don't speak out of turn and that they can wait and poll
774 * on the conversation.
775 */
776typedef struct RTPINGPONG
777{
778 /** The semaphore the Ping thread waits on. */
779 RTSEMEVENT Ping;
780 /** The semaphore the Pong thread waits on. */
781 RTSEMEVENT Pong;
782 /** The current speaker. */
783 volatile RTPINGPONGSPEAKER enmSpeaker;
784#if HC_ARCH_BITS == 64
785 /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
786 uint32_t u32Padding;
787#endif
788} RTPINGPONG;
789/** Pointer to Ping-Pong construct. */
790typedef RTPINGPONG *PRTPINGPONG;
791
792/**
793 * Init a Ping-Pong construct.
794 *
795 * @returns iprt status code.
796 * @param pPP Pointer to the ping-pong structure which needs initialization.
797 */
798RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
799
800/**
801 * Deletes a Ping-Pong construct.
802 *
803 * @returns iprt status code.
804 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
805 * (I.e. put into uninitialized state.)
806 */
807RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
808
809/**
810 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
811 * This is called by the ping thread.
812 *
813 * @returns iprt status code.
814 * @param pPP Pointer to the ping-pong structure to ping.
815 */
816RTDECL(int) RTSemPing(PRTPINGPONG pPP);
817
818/**
819 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
820 * This is called by the pong thread.
821 *
822 * @returns iprt status code.
823 * @param pPP Pointer to the ping-pong structure to pong.
824 */
825RTDECL(int) RTSemPong(PRTPINGPONG pPP);
826
827/**
828 * Wait function for the ping thread.
829 *
830 * @returns iprt status code.
831 * Will not return VERR_INTERRUPTED.
832 * @param pPP Pointer to the ping-pong structure to wait on.
833 * @param cMillies Number of milliseconds to wait.
834 */
835RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, unsigned cMillies);
836
837/**
838 * Wait function for the pong thread.
839 *
840 * @returns iprt status code.
841 * Will not return VERR_INTERRUPTED.
842 * @param pPP Pointer to the ping-pong structure to wait on.
843 * @param cMillies Number of milliseconds to wait.
844 */
845RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, unsigned cMillies);
846
847
848/**
849 * Checks if the pong thread is speaking.
850 *
851 * @returns true / false.
852 * @param pPP Pointer to the ping-pong structure.
853 * @remark This is NOT the same as !RTSemPongIsSpeaker().
854 */
855DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
856{
857 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
858 return enmSpeaker == RTPINGPONGSPEAKER_PING;
859}
860
861
862/**
863 * Checks if the pong thread is speaking.
864 *
865 * @returns true / false.
866 * @param pPP Pointer to the ping-pong structure.
867 * @remark This is NOT the same as !RTSemPingIsSpeaker().
868 */
869DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
870{
871 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
872 return enmSpeaker == RTPINGPONGSPEAKER_PONG;
873}
874
875
876/**
877 * Checks whether the ping thread should wait.
878 *
879 * @returns true / false.
880 * @param pPP Pointer to the ping-pong structure.
881 * @remark This is NOT the same as !RTSemPongShouldWait().
882 */
883DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
884{
885 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
886 return enmSpeaker == RTPINGPONGSPEAKER_PONG
887 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
888 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
889}
890
891
892/**
893 * Checks whether the pong thread should wait.
894 *
895 * @returns true / false.
896 * @param pPP Pointer to the ping-pong structure.
897 * @remark This is NOT the same as !RTSemPingShouldWait().
898 */
899DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
900{
901 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
902 return enmSpeaker == RTPINGPONGSPEAKER_PING
903 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
904 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
905}
906
907/** @} */
908
909
910/** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads
911 *
912 * The crossroads semaphore is intended to prevent two classes of incompatible
913 * events from occuring simultaneously, like south/north bound traffic and
914 * west/east bound traffic at a 4-way junction.
915 *
916 * @remarks In order to simplify the implementation, the current flow is always
917 * given priority. So, it won't work at all well when busy!
918 *
919 * @remarks "XRoads" is used as a name because it is briefer than "crossroads"
920 * and it slightly stresses that is a 4 way crossing to the users of
921 * American English.
922 * @{
923 */
924
925/**
926 * Creates a crossroads semaphore.
927 *
928 * @returns IPRT status code.
929 *
930 * @param phXRoads Where to return the handle to the newly created
931 * crossroads semaphore.
932 */
933RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads);
934
935/**
936 * Destroys a crossroads semaphore.
937 *
938 * @returns IPRT status code.
939 *
940 * @param hXRoads Handle to the crossroads semaphore that is to be
941 * destroyed. NIL_RTSEMXROADS is quitetly ignored
942 * (VINF_SUCCESS).
943 */
944RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads);
945
946/**
947 * Enter the crossroads from the south or north.
948 *
949 * (Coupled with RTSemXRoadsNSLeave.)
950 *
951 * @returns IPRT status code.
952 * @param hXRoads Handle to the crossroads semaphore.
953 */
954RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads);
955
956/**
957 * Leave the crossroads to the north or south.
958 *
959 * (Coupled with RTSemXRoadsNSEnter.)
960 *
961 * @returns IPRT status code.
962 * @param hXRoads Handle to the crossroads semaphore.
963 */
964RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads);
965
966/**
967 * Leave the crossroads from the east or west.
968 *
969 * (Coupled with RTSemXRoadsEWLeave.)
970 *
971 * @returns IPRT status code.
972 * @param hXRoads Handle to the crossroads semaphore.
973 */
974RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads);
975
976/**
977 * Leave the crossroads to the west or east.
978 *
979 * (Coupled with RTSemXRoadsEWEnter.)
980 *
981 * @returns IPRT status code.
982 * @param hXRoads Handle to the crossroads semaphore.
983 */
984RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads);
985
986/** @} */
987
988/** @} */
989
990RT_C_DECLS_END
991
992#endif
993
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