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_rwlock.h"
18#include "apr_private.h"
19
20#if APR_HAS_THREADS
21
22#ifdef HAVE_PTHREAD_RWLOCKS
23
24/* The rwlock must be initialized but not locked by any thread when
25 * cleanup is called. */
26static apr_status_t thread_rwlock_cleanup(void *data)
27{
28    apr_thread_rwlock_t *rwlock = (apr_thread_rwlock_t *)data;
29    apr_status_t stat;
30
31    stat = pthread_rwlock_destroy(&rwlock->rwlock);
32#ifdef HAVE_ZOS_PTHREADS
33    if (stat) {
34        stat = errno;
35    }
36#endif
37    return stat;
38}
39
40APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
41                                                   apr_pool_t *pool)
42{
43    apr_thread_rwlock_t *new_rwlock;
44    apr_status_t stat;
45
46    new_rwlock = apr_palloc(pool, sizeof(apr_thread_rwlock_t));
47    new_rwlock->pool = pool;
48
49    if ((stat = pthread_rwlock_init(&new_rwlock->rwlock, NULL))) {
50#ifdef HAVE_ZOS_PTHREADS
51        stat = errno;
52#endif
53        return stat;
54    }
55
56    apr_pool_cleanup_register(new_rwlock->pool,
57                              (void *)new_rwlock, thread_rwlock_cleanup,
58                              apr_pool_cleanup_null);
59
60    *rwlock = new_rwlock;
61    return APR_SUCCESS;
62}
63
64APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
65{
66    apr_status_t stat;
67
68    stat = pthread_rwlock_rdlock(&rwlock->rwlock);
69#ifdef HAVE_ZOS_PTHREADS
70    if (stat) {
71        stat = errno;
72    }
73#endif
74    return stat;
75}
76
77APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
78{
79    apr_status_t stat;
80
81    stat = pthread_rwlock_tryrdlock(&rwlock->rwlock);
82#ifdef HAVE_ZOS_PTHREADS
83    if (stat) {
84        stat = errno;
85    }
86#endif
87    /* Normalize the return code. */
88    if (stat == EBUSY)
89        stat = APR_EBUSY;
90    return stat;
91}
92
93APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
94{
95    apr_status_t stat;
96
97    stat = pthread_rwlock_wrlock(&rwlock->rwlock);
98#ifdef HAVE_ZOS_PTHREADS
99    if (stat) {
100        stat = errno;
101    }
102#endif
103    return stat;
104}
105
106APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
107{
108    apr_status_t stat;
109
110    stat = pthread_rwlock_trywrlock(&rwlock->rwlock);
111#ifdef HAVE_ZOS_PTHREADS
112    if (stat) {
113        stat = errno;
114    }
115#endif
116    /* Normalize the return code. */
117    if (stat == EBUSY)
118        stat = APR_EBUSY;
119    return stat;
120}
121
122APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
123{
124    apr_status_t stat;
125
126    stat = pthread_rwlock_unlock(&rwlock->rwlock);
127#ifdef HAVE_ZOS_PTHREADS
128    if (stat) {
129        stat = errno;
130    }
131#endif
132    return stat;
133}
134
135APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
136{
137    return apr_pool_cleanup_run(rwlock->pool, rwlock, thread_rwlock_cleanup);
138}
139
140#else  /* HAVE_PTHREAD_RWLOCKS */
141
142APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
143                                                   apr_pool_t *pool)
144{
145    return APR_ENOTIMPL;
146}
147
148APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
149{
150    return APR_ENOTIMPL;
151}
152
153APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
154{
155    return APR_ENOTIMPL;
156}
157
158APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
159{
160    return APR_ENOTIMPL;
161}
162
163APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
164{
165    return APR_ENOTIMPL;
166}
167
168APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
169{
170    return APR_ENOTIMPL;
171}
172
173APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
174{
175    return APR_ENOTIMPL;
176}
177
178#endif /* HAVE_PTHREAD_RWLOCKS */
179APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
180
181#endif /* APR_HAS_THREADS */
182