/src/httpd/srclib/apr/locks/unix/thread_mutex.c
Line | Count | Source (jump to first uncovered line) |
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 | 5.33k | { |
25 | 5.33k | apr_thread_mutex_t *mutex = data; |
26 | 5.33k | apr_status_t rv; |
27 | | |
28 | 5.33k | rv = pthread_mutex_destroy(&mutex->mutex); |
29 | | #ifdef HAVE_ZOS_PTHREADS |
30 | | if (rv) { |
31 | | rv = errno; |
32 | | } |
33 | | #endif |
34 | 5.33k | return rv; |
35 | 5.33k | } |
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 | 5.34k | { |
41 | 5.34k | apr_thread_mutex_t *new_mutex; |
42 | 5.34k | 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 | 5.34k | new_mutex = apr_pcalloc(pool, sizeof(apr_thread_mutex_t)); |
51 | 5.34k | new_mutex->pool = pool; |
52 | | |
53 | 5.34k | #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE |
54 | 5.34k | if (flags & APR_THREAD_MUTEX_NESTED) { |
55 | 5.34k | pthread_mutexattr_t mattr; |
56 | | |
57 | 5.34k | rv = pthread_mutexattr_init(&mattr); |
58 | 5.34k | if (rv) return rv; |
59 | | |
60 | 5.34k | rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); |
61 | 5.34k | if (rv) { |
62 | 0 | pthread_mutexattr_destroy(&mattr); |
63 | 0 | return rv; |
64 | 0 | } |
65 | | |
66 | 5.34k | rv = pthread_mutex_init(&new_mutex->mutex, &mattr); |
67 | | |
68 | 5.34k | pthread_mutexattr_destroy(&mattr); |
69 | 5.34k | } else |
70 | 0 | #endif |
71 | 0 | { |
72 | | #if defined(APR_THREAD_DEBUG) |
73 | | pthread_mutexattr_t mattr; |
74 | | |
75 | | rv = pthread_mutexattr_init(&mattr); |
76 | | if (rv) return rv; |
77 | | |
78 | | rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK); |
79 | | if (rv) { |
80 | | pthread_mutexattr_destroy(&mattr); |
81 | | return rv; |
82 | | } |
83 | | |
84 | | rv = pthread_mutex_init(&new_mutex->mutex, &mattr); |
85 | | |
86 | | pthread_mutexattr_destroy(&mattr); |
87 | | #else |
88 | 0 | rv = pthread_mutex_init(&new_mutex->mutex, NULL); |
89 | 0 | #endif |
90 | 0 | } |
91 | | |
92 | 5.34k | if (rv) { |
93 | | #ifdef HAVE_ZOS_PTHREADS |
94 | | rv = errno; |
95 | | #endif |
96 | 0 | return rv; |
97 | 0 | } |
98 | | |
99 | | #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK |
100 | | if (flags & APR_THREAD_MUTEX_TIMED) { |
101 | | rv = apr_thread_cond_create(&new_mutex->cond, pool); |
102 | | if (rv) { |
103 | | #ifdef HAVE_ZOS_PTHREADS |
104 | | rv = errno; |
105 | | #endif |
106 | | pthread_mutex_destroy(&new_mutex->mutex); |
107 | | return rv; |
108 | | } |
109 | | } |
110 | | #endif |
111 | | |
112 | 5.34k | apr_pool_cleanup_register(new_mutex->pool, |
113 | 5.34k | new_mutex, thread_mutex_cleanup, |
114 | 5.34k | apr_pool_cleanup_null); |
115 | | |
116 | 5.34k | *mutex = new_mutex; |
117 | 5.34k | return APR_SUCCESS; |
118 | 5.34k | } |
119 | | |
120 | | APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex) |
121 | 10.7k | { |
122 | 10.7k | apr_status_t rv; |
123 | | |
124 | | #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK |
125 | | if (mutex->cond) { |
126 | | apr_status_t rv2; |
127 | | |
128 | | rv = pthread_mutex_lock(&mutex->mutex); |
129 | | if (rv) { |
130 | | #ifdef HAVE_ZOS_PTHREADS |
131 | | rv = errno; |
132 | | #endif |
133 | | return rv; |
134 | | } |
135 | | |
136 | | if (mutex->locked) { |
137 | | mutex->num_waiters++; |
138 | | rv = apr_thread_cond_wait(mutex->cond, mutex); |
139 | | mutex->num_waiters--; |
140 | | } |
141 | | else { |
142 | | mutex->locked = 1; |
143 | | } |
144 | | |
145 | | rv2 = pthread_mutex_unlock(&mutex->mutex); |
146 | | if (rv2 && !rv) { |
147 | | #ifdef HAVE_ZOS_PTHREADS |
148 | | rv = errno; |
149 | | #else |
150 | | rv = rv2; |
151 | | #endif |
152 | | } |
153 | | |
154 | | return rv; |
155 | | } |
156 | | #endif |
157 | | |
158 | 10.7k | rv = pthread_mutex_lock(&mutex->mutex); |
159 | | #ifdef HAVE_ZOS_PTHREADS |
160 | | if (rv) { |
161 | | rv = errno; |
162 | | } |
163 | | #endif |
164 | | |
165 | 10.7k | return rv; |
166 | 10.7k | } |
167 | | |
168 | | APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) |
169 | 0 | { |
170 | 0 | apr_status_t rv; |
171 | |
|
172 | | #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK |
173 | | if (mutex->cond) { |
174 | | apr_status_t rv2; |
175 | | |
176 | | rv = pthread_mutex_lock(&mutex->mutex); |
177 | | if (rv) { |
178 | | #ifdef HAVE_ZOS_PTHREADS |
179 | | rv = errno; |
180 | | #endif |
181 | | return rv; |
182 | | } |
183 | | |
184 | | if (mutex->locked) { |
185 | | rv = APR_EBUSY; |
186 | | } |
187 | | else { |
188 | | mutex->locked = 1; |
189 | | } |
190 | | |
191 | | rv2 = pthread_mutex_unlock(&mutex->mutex); |
192 | | if (rv2) { |
193 | | #ifdef HAVE_ZOS_PTHREADS |
194 | | rv = errno; |
195 | | #else |
196 | | rv = rv2; |
197 | | #endif |
198 | | } |
199 | | |
200 | | return rv; |
201 | | } |
202 | | #endif |
203 | |
|
204 | 0 | rv = pthread_mutex_trylock(&mutex->mutex); |
205 | 0 | if (rv) { |
206 | | #ifdef HAVE_ZOS_PTHREADS |
207 | | rv = errno; |
208 | | #endif |
209 | 0 | return (rv == EBUSY) ? APR_EBUSY : rv; |
210 | 0 | } |
211 | | |
212 | 0 | return APR_SUCCESS; |
213 | 0 | } |
214 | | |
215 | | APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex, |
216 | | apr_interval_time_t timeout) |
217 | 0 | { |
218 | 0 | apr_status_t rv = APR_ENOTIMPL; |
219 | |
|
220 | 0 | #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK |
221 | 0 | if (timeout <= 0) { |
222 | 0 | rv = pthread_mutex_trylock(&mutex->mutex); |
223 | 0 | if (rv) { |
224 | | #ifdef HAVE_ZOS_PTHREADS |
225 | | rv = errno; |
226 | | #endif |
227 | 0 | if (rv == EBUSY) { |
228 | 0 | rv = APR_TIMEUP; |
229 | 0 | } |
230 | 0 | } |
231 | 0 | } |
232 | 0 | else { |
233 | 0 | struct timespec abstime; |
234 | |
|
235 | 0 | timeout += apr_time_now(); |
236 | 0 | abstime.tv_sec = apr_time_sec(timeout); |
237 | 0 | abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ |
238 | |
|
239 | 0 | rv = pthread_mutex_timedlock(&mutex->mutex, &abstime); |
240 | 0 | if (rv) { |
241 | | #ifdef HAVE_ZOS_PTHREADS |
242 | | rv = errno; |
243 | | #endif |
244 | 0 | if (rv == ETIMEDOUT) { |
245 | 0 | rv = APR_TIMEUP; |
246 | 0 | } |
247 | 0 | } |
248 | 0 | } |
249 | |
|
250 | | #else /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ |
251 | | |
252 | | if (mutex->cond) { |
253 | | rv = pthread_mutex_lock(&mutex->mutex); |
254 | | if (rv) { |
255 | | #ifdef HAVE_ZOS_PTHREADS |
256 | | rv = errno; |
257 | | #endif |
258 | | return rv; |
259 | | } |
260 | | |
261 | | if (mutex->locked) { |
262 | | if (timeout <= 0) { |
263 | | rv = APR_TIMEUP; |
264 | | } |
265 | | else { |
266 | | mutex->num_waiters++; |
267 | | do { |
268 | | rv = apr_thread_cond_timedwait(mutex->cond, mutex, |
269 | | timeout); |
270 | | if (rv) { |
271 | | #ifdef HAVE_ZOS_PTHREADS |
272 | | rv = errno; |
273 | | #endif |
274 | | break; |
275 | | } |
276 | | } while (mutex->locked); |
277 | | mutex->num_waiters--; |
278 | | } |
279 | | if (rv) { |
280 | | pthread_mutex_unlock(&mutex->mutex); |
281 | | return rv; |
282 | | } |
283 | | } |
284 | | |
285 | | mutex->locked = 1; |
286 | | |
287 | | rv = pthread_mutex_unlock(&mutex->mutex); |
288 | | if (rv) { |
289 | | #ifdef HAVE_ZOS_PTHREADS |
290 | | rv = errno; |
291 | | #endif |
292 | | return rv; |
293 | | } |
294 | | } |
295 | | |
296 | | #endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ |
297 | |
|
298 | 0 | return rv; |
299 | 0 | } |
300 | | |
301 | | APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) |
302 | 10.7k | { |
303 | 10.7k | apr_status_t status; |
304 | | |
305 | | #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK |
306 | | if (mutex->cond) { |
307 | | status = pthread_mutex_lock(&mutex->mutex); |
308 | | if (status) { |
309 | | #ifdef HAVE_ZOS_PTHREADS |
310 | | status = errno; |
311 | | #endif |
312 | | return status; |
313 | | } |
314 | | |
315 | | if (!mutex->locked) { |
316 | | status = APR_EINVAL; |
317 | | } |
318 | | else if (mutex->num_waiters) { |
319 | | status = apr_thread_cond_signal(mutex->cond); |
320 | | } |
321 | | if (status) { |
322 | | pthread_mutex_unlock(&mutex->mutex); |
323 | | return status; |
324 | | } |
325 | | |
326 | | mutex->locked = 0; |
327 | | } |
328 | | #endif |
329 | | |
330 | 10.7k | status = pthread_mutex_unlock(&mutex->mutex); |
331 | | #ifdef HAVE_ZOS_PTHREADS |
332 | | if (status) { |
333 | | status = errno; |
334 | | } |
335 | | #endif |
336 | | |
337 | 10.7k | return status; |
338 | 10.7k | } |
339 | | |
340 | | APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) |
341 | 0 | { |
342 | 0 | apr_status_t rv, rv2 = APR_SUCCESS; |
343 | |
|
344 | | #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK |
345 | | if (mutex->cond) { |
346 | | rv2 = apr_thread_cond_destroy(mutex->cond); |
347 | | } |
348 | | #endif |
349 | |
|
350 | 0 | rv = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup); |
351 | 0 | if (rv == APR_SUCCESS) { |
352 | 0 | rv = rv2; |
353 | 0 | } |
354 | |
|
355 | 0 | return rv; |
356 | 0 | } |
357 | | |
358 | | APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex) |
359 | | |
360 | | #endif /* APR_HAS_THREADS */ |