Coverage Report

Created: 2023-03-26 06:28

/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 */