]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/apr/locks/unix/thread_mutex.c
Update apr to 1.7.0. See contrib/apr/CHANGES for a summary of changes.
[FreeBSD/FreeBSD.git] / contrib / apr / locks / unix / thread_mutex.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_arch_thread_mutex.h"
18 #define APR_WANT_MEMFUNC
19 #include "apr_want.h"
20
21 #if APR_HAS_THREADS
22
23 static apr_status_t thread_mutex_cleanup(void *data)
24 {
25     apr_thread_mutex_t *mutex = data;
26     apr_status_t rv;
27
28     rv = pthread_mutex_destroy(&mutex->mutex);
29 #ifdef HAVE_ZOS_PTHREADS
30     if (rv) {
31         rv = errno;
32     }
33 #endif
34     return rv;
35
36
37 APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
38                                                   unsigned int flags,
39                                                   apr_pool_t *pool)
40 {
41     apr_thread_mutex_t *new_mutex;
42     apr_status_t rv;
43     
44 #ifndef HAVE_PTHREAD_MUTEX_RECURSIVE
45     if (flags & APR_THREAD_MUTEX_NESTED) {
46         return APR_ENOTIMPL;
47     }
48 #endif
49
50     new_mutex = apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
51     new_mutex->pool = pool;
52
53 #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
54     if (flags & APR_THREAD_MUTEX_NESTED) {
55         pthread_mutexattr_t mattr;
56         
57         rv = pthread_mutexattr_init(&mattr);
58         if (rv) return rv;
59         
60         rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
61         if (rv) {
62             pthread_mutexattr_destroy(&mattr);
63             return rv;
64         }
65          
66         rv = pthread_mutex_init(&new_mutex->mutex, &mattr);
67         
68         pthread_mutexattr_destroy(&mattr);
69     } else
70 #endif
71         rv = pthread_mutex_init(&new_mutex->mutex, NULL);
72
73     if (rv) {
74 #ifdef HAVE_ZOS_PTHREADS
75         rv = errno;
76 #endif
77         return rv;
78     }
79
80 #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
81     if (flags & APR_THREAD_MUTEX_TIMED) {
82         rv = apr_thread_cond_create(&new_mutex->cond, pool);
83         if (rv) {
84 #ifdef HAVE_ZOS_PTHREADS
85             rv = errno;
86 #endif
87             pthread_mutex_destroy(&new_mutex->mutex);
88             return rv;
89         }
90     }
91 #endif
92
93     apr_pool_cleanup_register(new_mutex->pool,
94                               new_mutex, thread_mutex_cleanup,
95                               apr_pool_cleanup_null);
96
97     *mutex = new_mutex;
98     return APR_SUCCESS;
99 }
100
101 APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
102 {
103     apr_status_t rv;
104
105     if (mutex->cond) {
106         apr_status_t rv2;
107
108         rv = pthread_mutex_lock(&mutex->mutex);
109         if (rv) {
110 #ifdef HAVE_ZOS_PTHREADS
111             rv = errno;
112 #endif
113             return rv;
114         }
115
116         if (mutex->locked) {
117             mutex->num_waiters++;
118             rv = apr_thread_cond_wait(mutex->cond, mutex);
119             mutex->num_waiters--;
120         }
121         else {
122             mutex->locked = 1;
123         }
124
125         rv2 = pthread_mutex_unlock(&mutex->mutex);
126         if (rv2 && !rv) {
127 #ifdef HAVE_ZOS_PTHREADS
128             rv = errno;
129 #else
130             rv = rv2;
131 #endif
132         }
133
134         return rv;
135     }
136
137     rv = pthread_mutex_lock(&mutex->mutex);
138 #ifdef HAVE_ZOS_PTHREADS
139     if (rv) {
140         rv = errno;
141     }
142 #endif
143
144     return rv;
145 }
146
147 APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
148 {
149     apr_status_t rv;
150
151     if (mutex->cond) {
152         apr_status_t rv2;
153
154         rv = pthread_mutex_lock(&mutex->mutex);
155         if (rv) {
156 #ifdef HAVE_ZOS_PTHREADS
157             rv = errno;
158 #endif
159             return rv;
160         }
161
162         if (mutex->locked) {
163             rv = APR_EBUSY;
164         }
165         else {
166             mutex->locked = 1;
167         }
168
169         rv2 = pthread_mutex_unlock(&mutex->mutex);
170         if (rv2) {
171 #ifdef HAVE_ZOS_PTHREADS
172             rv = errno;
173 #else
174             rv = rv2;
175 #endif
176         }
177
178         return rv;
179     }
180
181     rv = pthread_mutex_trylock(&mutex->mutex);
182     if (rv) {
183 #ifdef HAVE_ZOS_PTHREADS
184         rv = errno;
185 #endif
186         return (rv == EBUSY) ? APR_EBUSY : rv;
187     }
188
189     return APR_SUCCESS;
190 }
191
192 APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
193                                                  apr_interval_time_t timeout)
194 {
195     apr_status_t rv = APR_ENOTIMPL;
196 #if APR_HAS_TIMEDLOCKS
197
198 #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
199     if (timeout <= 0) {
200         rv = pthread_mutex_trylock(&mutex->mutex);
201         if (rv) {
202 #ifdef HAVE_ZOS_PTHREADS
203             rv = errno;
204 #endif
205             if (rv == EBUSY) {
206                 rv = APR_TIMEUP;
207             }
208         }
209     }
210     else {
211         struct timespec abstime;
212
213         timeout += apr_time_now();
214         abstime.tv_sec = apr_time_sec(timeout);
215         abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
216
217         rv = pthread_mutex_timedlock(&mutex->mutex, &abstime);
218         if (rv) {
219 #ifdef HAVE_ZOS_PTHREADS
220             rv = errno;
221 #endif
222             if (rv == ETIMEDOUT) {
223                 rv = APR_TIMEUP;
224             }
225         }
226     }
227
228 #else /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
229
230     if (mutex->cond) {
231         rv = pthread_mutex_lock(&mutex->mutex);
232         if (rv) {
233 #ifdef HAVE_ZOS_PTHREADS
234             rv = errno;
235 #endif
236             return rv;
237         }
238
239         if (mutex->locked) {
240             if (timeout <= 0) {
241                 rv = APR_TIMEUP;
242             }
243             else {
244                 mutex->num_waiters++;
245                 do {
246                     rv = apr_thread_cond_timedwait(mutex->cond, mutex,
247                                                    timeout);
248                     if (rv) {
249 #ifdef HAVE_ZOS_PTHREADS
250                         rv = errno;
251 #endif
252                         break;
253                     }
254                 } while (mutex->locked);
255                 mutex->num_waiters--;
256             }
257             if (rv) {
258                 pthread_mutex_unlock(&mutex->mutex);
259                 return rv;
260             }
261         }
262
263         mutex->locked = 1;
264
265         rv = pthread_mutex_unlock(&mutex->mutex);
266         if (rv) {
267 #ifdef HAVE_ZOS_PTHREADS
268             rv = errno;
269 #endif
270             return rv;
271         }
272     }
273
274 #endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
275
276 #endif /* APR_HAS_TIMEDLOCKS */
277     return rv;
278 }
279
280 APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
281 {
282     apr_status_t status;
283
284     if (mutex->cond) {
285         status = pthread_mutex_lock(&mutex->mutex);
286         if (status) {
287 #ifdef HAVE_ZOS_PTHREADS
288             status = errno;
289 #endif
290             return status;
291         }
292
293         if (!mutex->locked) {
294             status = APR_EINVAL;
295         }
296         else if (mutex->num_waiters) {
297             status = apr_thread_cond_signal(mutex->cond);
298         }
299         if (status) {
300             pthread_mutex_unlock(&mutex->mutex);
301             return status;
302         }
303
304         mutex->locked = 0;
305     }
306
307     status = pthread_mutex_unlock(&mutex->mutex);
308 #ifdef HAVE_ZOS_PTHREADS
309     if (status) {
310         status = errno;
311     }
312 #endif
313
314     return status;
315 }
316
317 APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
318 {
319     apr_status_t rv, rv2 = APR_SUCCESS;
320
321     if (mutex->cond) {
322         rv2 = apr_thread_cond_destroy(mutex->cond);
323     }
324     rv = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
325     if (rv == APR_SUCCESS) {
326         rv = rv2;
327     }
328     
329     return rv;
330 }
331
332 APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
333
334 #endif /* APR_HAS_THREADS */