~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/VBox/Runtime/semspingpong.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

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