VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/semspingpong.cpp@ 11836

Last change on this file since 11836 was 8245, checked in by vboxsync, 17 years ago

rebranding: IPRT files again.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.4 KB
Line 
1/* $Id: semspingpong.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */
2/** @file
3 * IPRT - Thread Ping-Pong Construct.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/semaphore.h>
36#include <iprt/thread.h>
37#include <iprt/asm.h>
38#include <iprt/assert.h>
39#include <iprt/err.h>
40
41
42
43/**
44 * Validates a pPP handle passed to one of the PP functions.
45 *
46 * @returns true if valid, false if invalid.
47 * @param pPP Pointe to the ping-pong structure.
48 */
49inline bool rtsemPPValid(PRTPINGPONG pPP)
50{
51 if (!VALID_PTR(pPP))
52 return false;
53
54 RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker;
55 if ( enmSpeaker != RTPINGPONGSPEAKER_PING
56 && enmSpeaker != RTPINGPONGSPEAKER_PONG
57 && enmSpeaker != RTPINGPONGSPEAKER_PONG_SIGNALED
58 && enmSpeaker != RTPINGPONGSPEAKER_PING_SIGNALED)
59 return false;
60
61 return true;
62}
63
64/**
65 * Init a Ping-Pong construct.
66 *
67 * @returns iprt status code.
68 * @param pPP Pointer to the ping-pong structure which needs initialization.
69 */
70RTR3DECL(int) RTSemPingPongInit(PRTPINGPONG pPP)
71{
72 /*
73 * Init the structure.
74 */
75 pPP->enmSpeaker = RTPINGPONGSPEAKER_PING;
76
77 int rc = RTSemEventCreate(&pPP->Ping);
78 if (RT_SUCCESS(rc))
79 {
80 rc = RTSemEventCreate(&pPP->Pong);
81 if (RT_SUCCESS(rc))
82 return VINF_SUCCESS;
83 RTSemEventDestroy(pPP->Ping);
84 }
85
86 return rc;
87}
88
89
90/**
91 * Destroys a Ping-Pong construct.
92 *
93 * @returns iprt status code.
94 * @param pPP Pointer to the ping-pong structure which is to be destroyed.
95 * (I.e. put into uninitialized state.)
96 */
97RTR3DECL(int) RTSemPingPongDestroy(PRTPINGPONG pPP)
98{
99 /*
100 * Validate input
101 */
102 if (!rtsemPPValid(pPP))
103 {
104 AssertMsgFailed(("Invalid input %p\n", pPP));
105 return VERR_INVALID_PARAMETER;
106 }
107
108 /*
109 * Invalidate the ping pong handle and destroy the event semaphores.
110 */
111 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_UNINITIALIZE);
112 int rc = RTSemEventDestroy(pPP->Ping);
113 int rc2 = RTSemEventDestroy(pPP->Pong);
114 AssertRC(rc);
115 AssertRC(rc2);
116
117 return VINF_SUCCESS;
118}
119
120
121/**
122 * Signals the pong thread in a ping-pong construct. (I.e. sends ping.)
123 * This is called by the ping thread.
124 *
125 * @returns iprt status code.
126 * @param pPP Pointer to the ping-pong structure to ping.
127 */
128RTR3DECL(int) RTSemPing(PRTPINGPONG pPP)
129{
130 /*
131 * Validate input
132 */
133 if (!rtsemPPValid(pPP))
134 {
135 AssertMsgFailed(("Invalid input %p\n", pPP));
136 return VERR_INVALID_PARAMETER;
137 }
138
139 if (pPP->enmSpeaker != RTPINGPONGSPEAKER_PING)
140 {
141 AssertMsgFailed(("Speaking out of turn!\n"));
142 return VERR_SEM_OUT_OF_TURN;
143 }
144
145 /*
146 * Signal the other thread.
147 */
148 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_PONG_SIGNALED);
149 int rc = RTSemEventSignal(pPP->Pong);
150 if (RT_SUCCESS(rc))
151 return rc;
152
153 /* restore the state. */
154 AssertMsgFailed(("Failed to signal pong sem %x. rc=%d\n", pPP->Pong, rc));
155 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_PING);
156 return rc;
157}
158
159
160/**
161 * Signals the ping thread in a ping-pong construct. (I.e. sends pong.)
162 * This is called by the pong thread.
163 *
164 * @returns iprt status code.
165 * @param pPP Pointer to the ping-pong structure to pong.
166 */
167RTR3DECL(int) RTSemPong(PRTPINGPONG pPP)
168{
169 /*
170 * Validate input
171 */
172 if (!rtsemPPValid(pPP))
173 {
174 AssertMsgFailed(("Invalid input %p\n", pPP));
175 return VERR_INVALID_PARAMETER;
176 }
177
178 if (pPP->enmSpeaker != RTPINGPONGSPEAKER_PONG)
179 {
180 AssertMsgFailed(("Speaking out of turn!\n"));
181 return VERR_SEM_OUT_OF_TURN;
182 }
183
184 /*
185 * Signal the other thread.
186 */
187 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_PING_SIGNALED);
188 int rc = RTSemEventSignal(pPP->Ping);
189 if (RT_SUCCESS(rc))
190 return rc;
191
192 /* restore the state. */
193 AssertMsgFailed(("Failed to signal ping sem %x. rc=%d\n", pPP->Ping, rc));
194 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_PONG);
195 return rc;
196}
197
198
199/**
200 * Wait function for the ping thread.
201 *
202 * @returns iprt status code.
203 * Will not return VERR_INTERRUPTED.
204 * @param pPP Pointer to the ping-pong structure to wait on.
205 * @param cMillies Number of milliseconds to wait.
206 */
207RTR3DECL(int) RTSemPingWait(PRTPINGPONG pPP, unsigned cMillies)
208{
209 /*
210 * Validate input
211 */
212 if (!rtsemPPValid(pPP))
213 {
214 AssertMsgFailed(("Invalid input %p\n", pPP));
215 return VERR_INVALID_PARAMETER;
216 }
217
218 if ( pPP->enmSpeaker != RTPINGPONGSPEAKER_PONG
219 && pPP->enmSpeaker != RTPINGPONGSPEAKER_PONG_SIGNALED
220 && pPP->enmSpeaker != RTPINGPONGSPEAKER_PING_SIGNALED)
221 {
222 AssertMsgFailed(("Listening out of turn! enmSpeaker=%d\n", pPP->enmSpeaker));
223 return VERR_SEM_OUT_OF_TURN;
224 }
225
226 /*
227 * Wait.
228 */
229 int rc = RTSemEventWait(pPP->Ping, cMillies);
230 if (RT_SUCCESS(rc))
231 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_PING);
232 Assert(rc != VERR_INTERRUPTED);
233 return rc;
234}
235
236
237/**
238 * Wait function for the pong thread.
239 *
240 * @returns iprt status code.
241 * Will not return VERR_INTERRUPTED.
242 * @param pPP Pointer to the ping-pong structure to wait on.
243 * @param cMillies Number of milliseconds to wait.
244 */
245RTR3DECL(int) RTSemPongWait(PRTPINGPONG pPP, unsigned cMillies)
246{
247 /*
248 * Validate input
249 */
250 if (!rtsemPPValid(pPP))
251 {
252 AssertMsgFailed(("Invalid input %p\n", pPP));
253 return VERR_INVALID_PARAMETER;
254 }
255
256 if ( pPP->enmSpeaker != RTPINGPONGSPEAKER_PING
257 && pPP->enmSpeaker != RTPINGPONGSPEAKER_PING_SIGNALED
258 && pPP->enmSpeaker != RTPINGPONGSPEAKER_PONG_SIGNALED)
259 {
260 AssertMsgFailed(("Listening out of turn! enmSpeaker=%d\n", pPP->enmSpeaker));
261 return VERR_SEM_OUT_OF_TURN;
262 }
263
264 /*
265 * Wait.
266 */
267 int rc = RTSemEventWait(pPP->Pong, cMillies);
268 if (RT_SUCCESS(rc))
269 ASMAtomicXchgSize(&pPP->enmSpeaker, RTPINGPONGSPEAKER_PONG);
270 Assert(rc != VERR_INTERRUPTED);
271 return rc;
272}
273
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