]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/apr/threadproc/unix/thread.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / apr / threadproc / unix / thread.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.h"
18 #include "apr_portable.h"
19 #include "apr_arch_threadproc.h"
20
21 #if APR_HAS_THREADS
22
23 #if APR_HAVE_PTHREAD_H
24
25 /* Destroy the threadattr object */
26 static apr_status_t threadattr_cleanup(void *data)
27 {
28     apr_threadattr_t *attr = data;
29     apr_status_t rv;
30
31     rv = pthread_attr_destroy(&attr->attr);
32 #ifdef HAVE_ZOS_PTHREADS
33     if (rv) {
34         rv = errno;
35     }
36 #endif
37     return rv;
38 }
39
40 APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new,
41                                                 apr_pool_t *pool)
42 {
43     apr_status_t stat;
44
45     (*new) = apr_palloc(pool, sizeof(apr_threadattr_t));
46     (*new)->pool = pool;
47     stat = pthread_attr_init(&(*new)->attr);
48
49     if (stat == 0) {
50         apr_pool_cleanup_register(pool, *new, threadattr_cleanup,
51                                   apr_pool_cleanup_null);
52         return APR_SUCCESS;
53     }
54 #ifdef HAVE_ZOS_PTHREADS
55     stat = errno;
56 #endif
57
58     return stat;
59 }
60
61 #if defined(PTHREAD_CREATE_DETACHED)
62 #define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)
63 #else
64 #define DETACH_ARG(v) ((v) ? 1 : 0)
65 #endif
66
67 APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr,
68                                                     apr_int32_t on)
69 {
70     apr_status_t stat;
71 #ifdef HAVE_ZOS_PTHREADS
72     int arg = DETACH_ARG(on);
73
74     if ((stat = pthread_attr_setdetachstate(&attr->attr, &arg)) == 0) {
75 #else
76     if ((stat = pthread_attr_setdetachstate(&attr->attr, 
77                                             DETACH_ARG(on))) == 0) {
78 #endif
79         return APR_SUCCESS;
80     }
81     else {
82 #ifdef HAVE_ZOS_PTHREADS
83         stat = errno;
84 #endif
85
86         return stat;
87     }
88 }
89
90 APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
91 {
92     int state;
93
94 #ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG
95     state = pthread_attr_getdetachstate(&attr->attr);
96 #else
97     pthread_attr_getdetachstate(&attr->attr, &state);
98 #endif
99     if (state == DETACH_ARG(1))
100         return APR_DETACH;
101     return APR_NOTDETACH;
102 }
103
104 APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
105                                                        apr_size_t stacksize)
106 {
107     int stat;
108
109     stat = pthread_attr_setstacksize(&attr->attr, stacksize);
110     if (stat == 0) {
111         return APR_SUCCESS;
112     }
113 #ifdef HAVE_ZOS_PTHREADS
114     stat = errno;
115 #endif
116
117     return stat;
118 }
119
120 APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
121                                                        apr_size_t size)
122 {
123 #ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE
124     apr_status_t rv;
125
126     rv = pthread_attr_setguardsize(&attr->attr, size);
127     if (rv == 0) {
128         return APR_SUCCESS;
129     }
130 #ifdef HAVE_ZOS_PTHREADS
131     rv = errno;
132 #endif
133     return rv;
134 #else
135     return APR_ENOTIMPL;
136 #endif
137 }
138
139 static void *dummy_worker(void *opaque)
140 {
141     apr_thread_t *thread = (apr_thread_t*)opaque;
142     return thread->func(thread, thread->data);
143 }
144
145 APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
146                                             apr_threadattr_t *attr,
147                                             apr_thread_start_t func,
148                                             void *data,
149                                             apr_pool_t *pool)
150 {
151     apr_status_t stat;
152     pthread_attr_t *temp;
153
154     (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
155
156     if ((*new) == NULL) {
157         return APR_ENOMEM;
158     }
159
160     (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t));
161
162     if ((*new)->td == NULL) {
163         return APR_ENOMEM;
164     }
165
166     (*new)->data = data;
167     (*new)->func = func;
168
169     if (attr)
170         temp = &attr->attr;
171     else
172         temp = NULL;
173
174     stat = apr_pool_create(&(*new)->pool, pool);
175     if (stat != APR_SUCCESS) {
176         return stat;
177     }
178
179     if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) {
180         return APR_SUCCESS;
181     }
182     else {
183 #ifdef HAVE_ZOS_PTHREADS
184         stat = errno;
185 #endif
186
187         return stat;
188     }
189 }
190
191 APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
192 {
193     return pthread_self();
194 }
195
196 APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1,
197                                      apr_os_thread_t tid2)
198 {
199     return pthread_equal(tid1, tid2);
200 }
201
202 APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd,
203                                           apr_status_t retval)
204 {
205     thd->exitval = retval;
206     apr_pool_destroy(thd->pool);
207     pthread_exit(NULL);
208     return APR_SUCCESS;
209 }
210
211 APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval,
212                                           apr_thread_t *thd)
213 {
214     apr_status_t stat;
215     apr_status_t *thread_stat;
216
217     if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) {
218         *retval = thd->exitval;
219         return APR_SUCCESS;
220     }
221     else {
222 #ifdef HAVE_ZOS_PTHREADS
223         stat = errno;
224 #endif
225
226         return stat;
227     }
228 }
229
230 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
231 {
232     apr_status_t stat;
233
234 #ifdef HAVE_ZOS_PTHREADS
235     if ((stat = pthread_detach(thd->td)) == 0) {
236 #else
237     if ((stat = pthread_detach(*thd->td)) == 0) {
238 #endif
239
240         return APR_SUCCESS;
241     }
242     else {
243 #ifdef HAVE_ZOS_PTHREADS
244         stat = errno;
245 #endif
246
247         return stat;
248     }
249 }
250
251 APR_DECLARE(void) apr_thread_yield(void)
252 {
253 #ifdef HAVE_PTHREAD_YIELD
254 #ifdef HAVE_ZOS_PTHREADS
255     pthread_yield(NULL);
256 #else
257     pthread_yield();
258 #endif /* HAVE_ZOS_PTHREADS */
259 #else
260 #ifdef HAVE_SCHED_YIELD
261     sched_yield();
262 #endif
263 #endif
264 }
265
266 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
267                                               apr_thread_t *thread)
268 {
269     return apr_pool_userdata_get(data, key, thread->pool);
270 }
271
272 APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
273                               apr_status_t (*cleanup)(void *),
274                               apr_thread_t *thread)
275 {
276     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
277 }
278
279 APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
280                                             apr_thread_t *thd)
281 {
282     *thethd = thd->td;
283     return APR_SUCCESS;
284 }
285
286 APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
287                                             apr_os_thread_t *thethd,
288                                             apr_pool_t *pool)
289 {
290     if (pool == NULL) {
291         return APR_ENOPOOL;
292     }
293
294     if ((*thd) == NULL) {
295         (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
296         (*thd)->pool = pool;
297     }
298
299     (*thd)->td = thethd;
300     return APR_SUCCESS;
301 }
302
303 APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
304                                                apr_pool_t *p)
305 {
306     static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
307
308     *control = apr_palloc(p, sizeof(**control));
309     (*control)->once = once_init;
310     return APR_SUCCESS;
311 }
312
313 APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
314                                           void (*func)(void))
315 {
316     return pthread_once(&control->once, func);
317 }
318
319 APR_POOL_IMPLEMENT_ACCESSOR(thread)
320
321 #endif  /* HAVE_PTHREAD_H */
322 #endif  /* APR_HAS_THREADS */
323
324 #if !APR_HAS_THREADS
325
326 /* avoid warning for no prototype */
327 APR_DECLARE(apr_status_t) apr_os_thread_get(void);
328
329 APR_DECLARE(apr_status_t) apr_os_thread_get(void)
330 {
331     return APR_ENOTIMPL;
332 }
333
334 #endif