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