VirtualBox

source: vbox/trunk/src/VBox/Runtime/semspingpong.cpp@ 3672

Last change on this file since 3672 was 2981, checked in by vboxsync, 18 years ago

InnoTek -> innotek: all the headers and comments.

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