xref: /trunk/main/sal/osl/unx/conditn.c (revision 7c5cbfde20e595d678c73935a8f75203773bea47)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 
25 #include "system.h"
26 #include <sal/types.h>
27 
28 #include <osl/conditn.h>
29 #include <osl/diagnose.h>
30 #include <osl/time.h>
31 
32 
33 typedef struct _oslConditionImpl
34 {
35     pthread_cond_t  m_Condition;
36     pthread_mutex_t m_Lock;
37     sal_Bool            m_State;
38 } oslConditionImpl;
39 
40 
41 /*****************************************************************************/
42 /* osl_createCondition */
43 /*****************************************************************************/
44 oslCondition SAL_CALL osl_createCondition()
45 {
46     oslConditionImpl* pCond;
47     int nRet=0;
48 
49     pCond = (oslConditionImpl*) malloc(sizeof(oslConditionImpl));
50 
51     OSL_ASSERT(pCond);
52 
53     if ( pCond == NULL )
54     {
55         return 0;
56     }
57 
58     pCond->m_State = sal_False;
59 
60     /* init condition variable with default attr. (PTHREAD_PROCESS_PRIVAT) */
61     nRet =  pthread_cond_init(&pCond->m_Condition, PTHREAD_CONDATTR_DEFAULT);
62     if ( nRet != 0 )
63     {
64         OSL_TRACE("osl_createCondition : condition init failed. Errno: %d; '%s'\n",
65                   nRet, strerror(nRet));
66 
67         free(pCond);
68         return 0;
69     }
70 
71     nRet = pthread_mutex_init(&pCond->m_Lock, PTHREAD_MUTEXATTR_DEFAULT);
72     if ( nRet != 0 )
73     {
74         OSL_TRACE("osl_createCondition : mutex init failed. Errno: %d; %s\n",
75                   nRet, strerror(nRet));
76 
77         nRet = pthread_cond_destroy(&pCond->m_Condition);
78         if ( nRet != 0 )
79         {
80             OSL_TRACE("osl_createCondition : destroy condition failed. Errno: %d; '%s'\n",
81                       nRet, strerror(nRet));
82         }
83 
84         free(pCond);
85         pCond = NULL;
86     }
87 
88     return (oslCondition)pCond;
89 }
90 
91 /*****************************************************************************/
92 /* osl_destroyCondition */
93 /*****************************************************************************/
94 void SAL_CALL osl_destroyCondition(oslCondition Condition)
95 {
96     oslConditionImpl* pCond;
97     int nRet = 0;
98 
99     if ( Condition )
100     {
101         pCond = (oslConditionImpl*)Condition;
102 
103         nRet = pthread_cond_destroy(&pCond->m_Condition);
104         if ( nRet != 0 )
105         {
106             OSL_TRACE("osl_destroyCondition : destroy condition failed. Errno: %d; '%s'\n",
107                       nRet, strerror(nRet));
108         }
109         nRet = pthread_mutex_destroy(&pCond->m_Lock);
110         if ( nRet != 0 )
111         {
112             OSL_TRACE("osl_destroyCondition : destroy mutex failed. Errno: %d; '%s'\n",
113                       nRet, strerror(nRet));
114         }
115 
116         free(Condition);
117     }
118 
119     return;
120 }
121 
122 /*****************************************************************************/
123 /* osl_setCondition */
124 /*****************************************************************************/
125 sal_Bool SAL_CALL osl_setCondition(oslCondition Condition)
126 {
127    oslConditionImpl* pCond;
128    int nRet=0;
129 
130    OSL_ASSERT(Condition);
131    pCond = (oslConditionImpl*)Condition;
132 
133    if ( pCond == NULL )
134    {
135        return sal_False;
136    }
137 
138    nRet = pthread_mutex_lock(&pCond->m_Lock);
139    if ( nRet != 0 )
140    {
141        OSL_TRACE("osl_setCondition : mutex lock failed. Errno: %d; %s\n",
142                   nRet, strerror(nRet));
143        return sal_False;
144    }
145 
146    pCond->m_State = sal_True;
147    nRet = pthread_cond_broadcast(&pCond->m_Condition);
148    if ( nRet != 0 )
149    {
150        OSL_TRACE("osl_setCondition : condition broadcast failed. Errno: %d; %s\n",
151                   nRet, strerror(nRet));
152        (void)pthread_mutex_unlock(&pCond->m_Lock);
153        return sal_False;
154    }
155 
156    nRet = pthread_mutex_unlock(&pCond->m_Lock);
157    if ( nRet != 0 )
158    {
159        OSL_TRACE("osl_setCondition : mutex unlock failed. Errno: %d; %s\n",
160                   nRet, strerror(nRet));
161        return sal_False;
162    }
163 
164    return sal_True;
165 
166 }
167 
168 /*****************************************************************************/
169 /* osl_resetCondition */
170 /*****************************************************************************/
171 sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition)
172 {
173     oslConditionImpl* pCond;
174     int nRet=0;
175 
176     OSL_ASSERT(Condition);
177 
178     pCond = (oslConditionImpl*)Condition;
179 
180     if ( pCond == NULL )
181     {
182         return sal_False;
183     }
184 
185     nRet = pthread_mutex_lock(&pCond->m_Lock);
186     if ( nRet != 0 )
187     {
188        OSL_TRACE("osl_resetCondition : mutex lock failed. Errno: %d; %s\n",
189                   nRet, strerror(nRet));
190         return sal_False;
191     }
192 
193     pCond->m_State = sal_False;
194 
195     nRet = pthread_mutex_unlock(&pCond->m_Lock);
196     if ( nRet != 0 )
197     {
198        OSL_TRACE("osl_resetCondition : mutex unlock failed. Errno: %d; %s\n",
199                   nRet, strerror(nRet));
200         return sal_False;
201     }
202 
203     return sal_True;
204 }
205 
206 /*****************************************************************************/
207 /* osl_waitCondition */
208 /*****************************************************************************/
209 oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition, const TimeValue* pTimeout)
210 {
211     oslConditionImpl* pCond;
212     int nRet=0;
213     oslConditionResult Result = osl_cond_result_ok;
214 
215     OSL_ASSERT(Condition);
216     pCond = (oslConditionImpl*)Condition;
217 
218     if ( pCond == NULL )
219     {
220         return osl_cond_result_error;
221     }
222 
223     nRet = pthread_mutex_lock(&pCond->m_Lock);
224     if ( nRet != 0 )
225     {
226        OSL_TRACE("osl_waitCondition : mutex lock failed. Errno: %d; %s\n",
227                   nRet, strerror(nRet));
228         return osl_cond_result_error;
229     }
230 
231     if ( pTimeout )
232     {
233         if ( ! pCond->m_State )
234         {
235             int                 ret;
236             struct timeval      tp;
237             struct timespec     to;
238 
239             gettimeofday(&tp, NULL);
240 
241             SET_TIMESPEC( to, tp.tv_sec + pTimeout->Seconds,
242                               tp.tv_usec * 1000 + pTimeout->Nanosec );
243 
244             /* spurious wake up prevention */
245             do
246             {
247                 ret = pthread_cond_timedwait(&pCond->m_Condition, &pCond->m_Lock, &to);
248                 if ( ret != 0 )
249                 {
250                     if ( ret == ETIME || ret == ETIMEDOUT )
251                     {
252                         Result = osl_cond_result_timeout;
253                         nRet = pthread_mutex_unlock(&pCond->m_Lock);
254                         if (nRet != 0)
255                         {
256                             OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
257                                       nRet, strerror(nRet));
258                         }
259 
260                         return Result;
261                     }
262                     else if ( ret != EINTR )
263                     {
264                         Result = osl_cond_result_error;
265                         nRet = pthread_mutex_unlock(&pCond->m_Lock);
266                         if ( nRet != 0 )
267                         {
268                             OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
269                                       nRet, strerror(nRet));
270                         }
271                         return Result;
272                     }
273 /*                    OSL_TRACE("EINTR\n");*/
274                 }
275             }
276             while ( !pCond->m_State );
277         }
278     }
279     else
280     {
281         while ( !pCond->m_State )
282         {
283             nRet = pthread_cond_wait(&pCond->m_Condition, &pCond->m_Lock);
284             if ( nRet != 0 )
285             {
286                 OSL_TRACE("osl_waitCondition : condition wait failed. Errno: %d; %s\n",
287                           nRet, strerror(nRet));
288                 Result = osl_cond_result_error;
289                 nRet = pthread_mutex_unlock(&pCond->m_Lock);
290                 if ( nRet != 0 )
291                 {
292                     OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
293                               nRet, strerror(nRet));
294                 }
295 
296                 return Result;
297             }
298         }
299     }
300 
301     nRet = pthread_mutex_unlock(&pCond->m_Lock);
302     if ( nRet != 0 )
303     {
304         OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
305                   nRet, strerror(nRet));
306     }
307 
308     return Result;
309 }
310 
311 /*****************************************************************************/
312 /* osl_checkCondition */
313 /*****************************************************************************/
314 sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition)
315 {
316     sal_Bool State;
317     oslConditionImpl* pCond;
318     int nRet=0;
319 
320     OSL_ASSERT(Condition);
321     pCond = (oslConditionImpl*)Condition;
322 
323     if ( pCond == NULL )
324     {
325         return sal_False;
326     }
327 
328     nRet = pthread_mutex_lock(&pCond->m_Lock);
329     if ( nRet != 0 )
330     {
331         OSL_TRACE("osl_checkCondition : mutex unlock failed. Errno: %d; %s\n",
332                   nRet, strerror(nRet));
333     }
334 
335     State = pCond->m_State;
336 
337     nRet = pthread_mutex_unlock(&pCond->m_Lock);
338     if ( nRet != 0 )
339     {
340         OSL_TRACE("osl_checkCondition : mutex unlock failed. Errno: %d; %s\n",
341                   nRet, strerror(nRet));
342     }
343 
344     return State;
345 }
346 
347 
348