VirtualBox

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

Last change on this file since 16214 was 12874, checked in by vboxsync, 16 years ago

IPRT: added a testcase for RTSemPingPong and some state inspection methods.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.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
37__BEGIN_DECLS
38
39/** @defgroup grp_rt_sems RTSem - Semaphores
40 * @ingroup grp_rt
41 * @{
42 */
43
44
45/**
46 * Create a event semaphore.
47 *
48 * @returns iprt status code.
49 * @param pEventSem Where to store the event semaphore handle.
50 */
51RTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem);
52
53/**
54 * Destroy an event semaphore.
55 *
56 * @returns iprt status code.
57 * @param EventSem Handle of the
58 */
59RTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem);
60
61/**
62 * Signal an event semaphore.
63 *
64 * The event semaphore will be signaled and automatically reset
65 * after exactly one thread have successfully returned from
66 * RTSemEventWait() after waiting/polling on that semaphore.
67 *
68 * @returns iprt status code.
69 * @param EventSem The event semaphore to signal.
70 */
71RTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem);
72
73/**
74 * Wait for the event semaphore to be signaled, resume on interruption.
75 *
76 * This function will resume if the wait is interrupted by an async
77 * system event (like a unix signal) or similar.
78 *
79 * @returns iprt status code.
80 * Will not return VERR_INTERRUPTED.
81 * @param EventSem The event semaphore to wait on.
82 * @param cMillies Number of milliseconds to wait.
83 */
84RTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies);
85
86/**
87 * Wait for the event semaphore to be signaled, return on interruption.
88 *
89 * This function will not resume the wait if interrupted.
90 *
91 * @returns iprt status code.
92 * @param EventSem The event semaphore to wait on.
93 * @param cMillies Number of milliseconds to wait.
94 */
95RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies);
96
97
98
99/**
100 * Create a event multi semaphore.
101 *
102 * @returns iprt status code.
103 * @param pEventMultiSem Where to store the event multi semaphore handle.
104 */
105RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem);
106
107/**
108 * Destroy an event multi semaphore.
109 *
110 * @returns iprt status code.
111 * @param EventMultiSem The event multi sempahore to destroy.
112 */
113RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem);
114
115/**
116 * Signal an event multi semaphore.
117 *
118 * @returns iprt status code.
119 * @param EventMultiSem The event multi semaphore to signal.
120 */
121RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem);
122
123/**
124 * Resets an event multi semaphore to non-signaled state.
125 *
126 * @returns iprt status code.
127 * @param EventMultiSem The event multi semaphore to reset.
128 */
129RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem);
130
131/**
132 * Wait for the event multi semaphore to be signaled, resume on interruption.
133 *
134 * This function will resume if the wait is interrupted by an async
135 * system event (like a unix signal) or similar.
136 *
137 * @returns iprt status code.
138 * Will not return VERR_INTERRUPTED.
139 * @param EventMultiSem The event multi semaphore to wait on.
140 * @param cMillies Number of milliseconds to wait.
141 */
142RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies);
143
144
145/**
146 * Wait for the event multi semaphore to be signaled, return on interruption.
147 *
148 * This function will not resume the wait if interrupted.
149 *
150 * @returns iprt status code.
151 * @param EventMultiSem The event multi semaphore to wait on.
152 * @param cMillies Number of milliseconds to wait.
153 */
154RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies);
155
156
157
158/**
159 * Create a mutex semaphore.
160 *
161 * @returns iprt status code.
162 * @param pMutexSem Where to store the mutex semaphore handle.
163 */
164RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem);
165
166/**
167 * Destroy a mutex semaphore.
168 *
169 * @returns iprt status code.
170 * @param MutexSem The mutex semaphore to destroy.
171 */
172RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem);
173
174/**
175 * Request ownership of a mutex semaphore, resume on interruption.
176 *
177 * This function will resume if the wait is interrupted by an async
178 * system event (like a unix signal) or similar.
179 *
180 * The same thread may request a mutex semaphore multiple times,
181 * a nested counter is kept to make sure it's released on the right
182 * RTSemMutexRelease() call.
183 *
184 * @returns iprt status code.
185 * Will not return VERR_INTERRUPTED.
186 * @param MutexSem The mutex semaphore to request ownership over.
187 * @param cMillies The number of milliseconds to wait.
188 */
189RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies);
190
191/**
192 * Request ownership of a mutex semaphore, return on interruption.
193 *
194 * This function will not resume the wait if interrupted.
195 *
196 * The same thread may request a mutex semaphore multiple times,
197 * a nested counter is kept to make sure it's released on the right
198 * RTSemMutexRelease() call.
199 *
200 * @returns iprt status code.
201 * @param MutexSem The mutex semaphore to request ownership over.
202 * @param cMillies The number of milliseconds to wait.
203 */
204RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies);
205
206/**
207 * Release the ownership of a mutex semaphore.
208 *
209 * @returns iprt status code.
210 * @param MutexSem The mutex to release the ownership of.
211 * It goes without saying the the calling thread must own it.
212 */
213RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem);
214
215
216/**
217 * Create a fast mutex semaphore.
218 *
219 * @returns iprt status code.
220 * @param pMutexSem Where to store the mutex semaphore handle.
221 *
222 * @remarks Fast mutex semaphores are not recursive.
223 */
224RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX pMutexSem);
225
226/**
227 * Destroy a fast mutex semaphore.
228 *
229 * @returns iprt status code.
230 * @param MutexSem The mutex semaphore to destroy.
231 */
232RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX MutexSem);
233
234/**
235 * Request ownership of a fast mutex semaphore.
236 *
237 * The same thread may request a mutex semaphore multiple times,
238 * a nested counter is kept to make sure it's released on the right
239 * RTSemMutexRelease() call.
240 *
241 * @returns iprt status code.
242 * @param MutexSem The mutex semaphore to request ownership over.
243 */
244RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX MutexSem);
245
246/**
247 * Release the ownership of a fast mutex semaphore.
248 *
249 * @returns iprt status code.
250 * @param MutexSem The mutex to release the ownership of.
251 * It goes without saying the the calling thread must own it.
252 */
253RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX MutexSem);
254
255
256/**
257 * Creates a read/write semaphore.
258 *
259 * @returns iprt status code.
260 * @param pRWSem Where to store the handle to the created RW semaphore.
261 */
262RTDECL(int) RTSemRWCreate(PRTSEMRW pRWSem);
263
264/**
265 * Destroys a read/write semaphore.
266 *
267 * @returns iprt status code.
268 * @param RWSem The Read/Write semaphore to destroy.
269 */
270RTDECL(int) RTSemRWDestroy(RTSEMRW RWSem);
271
272/**
273 * Request read access to a read/write semaphore, resume on interruption
274 *
275 * @returns iprt status code.
276 * @retval VINF_SUCCESS on success.
277 * @retval VERR_INTERRUPT if the wait was interrupted.
278 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
279 *
280 * @param RWSem The Read/Write semaphore to request read access to.
281 * @param cMillies The number of milliseconds to wait.
282 */
283RTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies);
284
285/**
286 * Request read access to a read/write semaphore, return on interruption
287 *
288 * @returns iprt status code.
289 * @retval VINF_SUCCESS on success.
290 * @retval VERR_INTERRUPT if the wait was interrupted.
291 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
292 *
293 * @param RWSem The Read/Write semaphore to request read access to.
294 * @param cMillies The number of milliseconds to wait.
295 */
296RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies);
297
298/**
299 * Release read access to a read/write semaphore.
300 *
301 * @returns iprt status code.
302 * @param RWSem The Read/Write sempahore to release read access to.
303 * Goes without saying that caller must have read access to the sem.
304 */
305RTDECL(int) RTSemRWReleaseRead(RTSEMRW RWSem);
306
307/**
308 * Request write access to a read/write semaphore, resume on interruption.
309 *
310 * @returns iprt status code.
311 * @retval VINF_SUCCESS on success.
312 * @retval VERR_DEADLOCK if the caller owned the read lock.
313 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
314 *
315 * @param RWSem The Read/Write semaphore to request write access to.
316 * @param cMillies The number of milliseconds to wait.
317 */
318RTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies);
319
320/**
321 * Request write access to a read/write semaphore, return on interruption.
322 *
323 * @returns iprt status code.
324 * @retval VINF_SUCCESS on success.
325 * @retval VERR_INTERRUPT if the wait was interrupted.
326 * @retval VERR_DEADLOCK if the caller owned the read lock.
327 * @retval VERR_INVALID_HANDLE if RWSem is invalid.
328 *
329 * @param RWSem The Read/Write semaphore to request write access to.
330 * @param cMillies The number of milliseconds to wait.
331 */
332RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies);
333
334/**
335 * Release write access to a read/write semaphore.
336 *
337 * @returns iprt status code.
338 * @param RWSem The Read/Write sempahore to release read access to.
339 * Goes without saying that caller must have write access to the sem.
340 */
341RTDECL(int) RTSemRWReleaseWrite(RTSEMRW RWSem);
342
343/**
344 * Checks if the caller is the exclusive semaphore owner.
345 *
346 * @returns true / false accoringly.
347 * @param RWSem The Read/Write semaphore in question.
348 */
349RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW RWSem);
350
351/**
352 * Gets the write recursion count.
353 *
354 * @returns The write recursion count (0 if bad semaphore handle).
355 * @param RWSem The Read/Write semaphore in question.
356 */
357RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW RWSem);
358
359/**
360 * Gets the read recursion count of the current writer.
361 *
362 * @returns The read recursion count (0 if bad semaphore handle).
363 * @param RWSem The Read/Write semaphore in question.
364 */
365RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW RWSem);
366
367
368
369/**
370 * Ping-pong speaker
371 */
372typedef enum RTPINGPONGSPEAKER
373{
374 /** Not initialized. */
375 RTPINGPONGSPEAKER_UNINITIALIZE = 0,
376 /** Ping is speaking, Pong is waiting. */
377 RTPINGPONGSPEAKER_PING,
378 /** Pong is signaled, Ping is waiting. */
379 RTPINGPONGSPEAKER_PONG_SIGNALED,
380 /** Pong is speaking, Ping is waiting. */
381 RTPINGPONGSPEAKER_PONG,
382 /** Ping is signaled, Pong is waiting. */
383 RTPINGPONGSPEAKER_PING_SIGNALED,
384 /** Hack to ensure that it's at least 32-bits wide. */
385 RTPINGPONGSPEAKER_HACK = 0x7fffffff
386} RTPINGPONGSPEAKER;
387
388/**
389 * Ping-Pong construct.
390 *
391 * Two threads, one saying Ping and the other saying Pong. The construct
392 * makes sure they don't speak out of turn and that they can wait and poll
393 * on the conversation.
394 */
395typedef struct RTPINGPONG
396{
397 /** The semaphore the Ping thread waits on. */
398 RTSEMEVENT Ping;
399 /** The semaphore the Pong thread waits on. */
400 RTSEMEVENT Pong;
401 /** The current speaker. */
402 volatile RTPINGPONGSPEAKER enmSpeaker;
403#if HC_ARCH_BITS == 64
404 /** Padding the structure to become a multiple of sizeof(RTHCPTR). */
405 uint32_t u32Padding;
406#endif
407} RTPINGPONG;
408/** Pointer to Ping-Pong construct. */
409typedef RTPINGPONG *PRTPINGPONG;
410
411/**
412 * Init a Ping-Pong construct.
413 *
414 * @returns iprt status code.
415 * @param pPP Pointer to the ping-pong structure which needs initialization.
416 */
417RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP);
418
419/**
420 * Deletes a Ping-Pong construct.
421 *
422 * @returns iprt status code.
423 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
424 * (I.e. put into uninitialized state.)
425 */
426RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP);
427
428/**
429 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
430 * This is called by the ping thread.
431 *
432 * @returns iprt status code.
433 * @param pPP Pointer to the ping-pong structure to ping.
434 */
435RTDECL(int) RTSemPing(PRTPINGPONG pPP);
436
437/**
438 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
439 * This is called by the pong thread.
440 *
441 * @returns iprt status code.
442 * @param pPP Pointer to the ping-pong structure to pong.
443 */
444RTDECL(int) RTSemPong(PRTPINGPONG pPP);
445
446/**
447 * Wait function for the ping thread.
448 *
449 * @returns iprt status code.
450 * Will not return VERR_INTERRUPTED.
451 * @param pPP Pointer to the ping-pong structure to wait on.
452 * @param cMillies Number of milliseconds to wait.
453 */
454RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, unsigned cMillies);
455
456/**
457 * Wait function for the pong thread.
458 *
459 * @returns iprt status code.
460 * Will not return VERR_INTERRUPTED.
461 * @param pPP Pointer to the ping-pong structure to wait on.
462 * @param cMillies Number of milliseconds to wait.
463 */
464RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, unsigned cMillies);
465
466
467/**
468 * Checks if the pong thread is speaking.
469 *
470 * @returns true / false.
471 * @param pPP Pointer to the ping-pong structure.
472 * @remark This is NOT the same as !RTSemPongIsSpeaker().
473 */
474DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP)
475{
476 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
477 return enmSpeaker == RTPINGPONGSPEAKER_PING;
478}
479
480
481/**
482 * Checks if the pong thread is speaking.
483 *
484 * @returns true / false.
485 * @param pPP Pointer to the ping-pong structure.
486 * @remark This is NOT the same as !RTSemPingIsSpeaker().
487 */
488DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP)
489{
490 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
491 return enmSpeaker == RTPINGPONGSPEAKER_PONG;
492}
493
494
495/**
496 * Checks whether the ping thread should wait.
497 *
498 * @returns true / false.
499 * @param pPP Pointer to the ping-pong structure.
500 * @remark This is NOT the same as !RTSemPongShouldWait().
501 */
502DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP)
503{
504 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
505 return enmSpeaker == RTPINGPONGSPEAKER_PONG
506 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
507 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED;
508}
509
510
511/**
512 * Checks whether the pong thread should wait.
513 *
514 * @returns true / false.
515 * @param pPP Pointer to the ping-pong structure.
516 * @remark This is NOT the same as !RTSemPingShouldWait().
517 */
518DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP)
519{
520 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
521 return enmSpeaker == RTPINGPONGSPEAKER_PING
522 || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED
523 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED;
524}
525
526
527/** @} */
528
529__END_DECLS
530
531#endif
532
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