1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251875Speter * contributor license agreements.  See the NOTICE file distributed with
3251875Speter * this work for additional information regarding copyright ownership.
4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251875Speter * (the "License"); you may not use this file except in compliance with
6251875Speter * the License.  You may obtain a copy of the License at
7251875Speter *
8251875Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251875Speter *
10251875Speter * Unless required by applicable law or agreed to in writing, software
11251875Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251875Speter * See the License for the specific language governing permissions and
14251875Speter * limitations under the License.
15251875Speter */
16251875Speter
17251875Speter#include "apr.h"
18251875Speter#include "apr_portable.h"
19251875Speter#include "apr_arch_threadproc.h"
20251875Speter
21251875Speter#if APR_HAS_THREADS
22251875Speter
23251875Speter#if APR_HAVE_PTHREAD_H
24251875Speter
25251875Speter/* Destroy the threadattr object */
26251875Speterstatic apr_status_t threadattr_cleanup(void *data)
27251875Speter{
28251875Speter    apr_threadattr_t *attr = data;
29251875Speter    apr_status_t rv;
30251875Speter
31251875Speter    rv = pthread_attr_destroy(&attr->attr);
32251875Speter#ifdef HAVE_ZOS_PTHREADS
33251875Speter    if (rv) {
34251875Speter        rv = errno;
35251875Speter    }
36251875Speter#endif
37251875Speter    return rv;
38251875Speter}
39251875Speter
40251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new,
41251875Speter                                                apr_pool_t *pool)
42251875Speter{
43251875Speter    apr_status_t stat;
44251875Speter
45251875Speter    (*new) = apr_palloc(pool, sizeof(apr_threadattr_t));
46251875Speter    (*new)->pool = pool;
47251875Speter    stat = pthread_attr_init(&(*new)->attr);
48251875Speter
49251875Speter    if (stat == 0) {
50251875Speter        apr_pool_cleanup_register(pool, *new, threadattr_cleanup,
51251875Speter                                  apr_pool_cleanup_null);
52251875Speter        return APR_SUCCESS;
53251875Speter    }
54251875Speter#ifdef HAVE_ZOS_PTHREADS
55251875Speter    stat = errno;
56251875Speter#endif
57251875Speter
58251875Speter    return stat;
59251875Speter}
60251875Speter
61251875Speter#if defined(PTHREAD_CREATE_DETACHED)
62251875Speter#define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)
63251875Speter#else
64251875Speter#define DETACH_ARG(v) ((v) ? 1 : 0)
65251875Speter#endif
66251875Speter
67251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr,
68251875Speter                                                    apr_int32_t on)
69251875Speter{
70251875Speter    apr_status_t stat;
71251875Speter#ifdef HAVE_ZOS_PTHREADS
72251875Speter    int arg = DETACH_ARG(on);
73251875Speter
74251875Speter    if ((stat = pthread_attr_setdetachstate(&attr->attr, &arg)) == 0) {
75251875Speter#else
76251875Speter    if ((stat = pthread_attr_setdetachstate(&attr->attr,
77251875Speter                                            DETACH_ARG(on))) == 0) {
78251875Speter#endif
79251875Speter        return APR_SUCCESS;
80251875Speter    }
81251875Speter    else {
82251875Speter#ifdef HAVE_ZOS_PTHREADS
83251875Speter        stat = errno;
84251875Speter#endif
85251875Speter
86251875Speter        return stat;
87251875Speter    }
88251875Speter}
89251875Speter
90251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
91251875Speter{
92251875Speter    int state;
93251875Speter
94251875Speter#ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG
95251875Speter    state = pthread_attr_getdetachstate(&attr->attr);
96251875Speter#else
97251875Speter    pthread_attr_getdetachstate(&attr->attr, &state);
98251875Speter#endif
99253734Speter    if (state == DETACH_ARG(1))
100251875Speter        return APR_DETACH;
101251875Speter    return APR_NOTDETACH;
102251875Speter}
103251875Speter
104251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
105251875Speter                                                       apr_size_t stacksize)
106251875Speter{
107251875Speter    int stat;
108251875Speter
109251875Speter    stat = pthread_attr_setstacksize(&attr->attr, stacksize);
110251875Speter    if (stat == 0) {
111251875Speter        return APR_SUCCESS;
112251875Speter    }
113251875Speter#ifdef HAVE_ZOS_PTHREADS
114251875Speter    stat = errno;
115251875Speter#endif
116251875Speter
117251875Speter    return stat;
118251875Speter}
119251875Speter
120251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
121251875Speter                                                       apr_size_t size)
122251875Speter{
123251875Speter#ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE
124251875Speter    apr_status_t rv;
125251875Speter
126251875Speter    rv = pthread_attr_setguardsize(&attr->attr, size);
127251875Speter    if (rv == 0) {
128251875Speter        return APR_SUCCESS;
129251875Speter    }
130251875Speter#ifdef HAVE_ZOS_PTHREADS
131251875Speter    rv = errno;
132251875Speter#endif
133251875Speter    return rv;
134251875Speter#else
135251875Speter    return APR_ENOTIMPL;
136251875Speter#endif
137251875Speter}
138251875Speter
139251875Speterstatic void *dummy_worker(void *opaque)
140251875Speter{
141251875Speter    apr_thread_t *thread = (apr_thread_t*)opaque;
142251875Speter    return thread->func(thread, thread->data);
143251875Speter}
144251875Speter
145251875SpeterAPR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
146251875Speter                                            apr_threadattr_t *attr,
147251875Speter                                            apr_thread_start_t func,
148251875Speter                                            void *data,
149251875Speter                                            apr_pool_t *pool)
150251875Speter{
151251875Speter    apr_status_t stat;
152251875Speter    pthread_attr_t *temp;
153251875Speter
154251875Speter    (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
155251875Speter
156251875Speter    if ((*new) == NULL) {
157251875Speter        return APR_ENOMEM;
158251875Speter    }
159251875Speter
160251875Speter    (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t));
161251875Speter
162251875Speter    if ((*new)->td == NULL) {
163251875Speter        return APR_ENOMEM;
164251875Speter    }
165251875Speter
166251875Speter    (*new)->data = data;
167251875Speter    (*new)->func = func;
168251875Speter
169251875Speter    if (attr)
170251875Speter        temp = &attr->attr;
171251875Speter    else
172251875Speter        temp = NULL;
173251875Speter
174251875Speter    stat = apr_pool_create(&(*new)->pool, pool);
175251875Speter    if (stat != APR_SUCCESS) {
176251875Speter        return stat;
177251875Speter    }
178251875Speter
179251875Speter    if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) {
180251875Speter        return APR_SUCCESS;
181251875Speter    }
182251875Speter    else {
183251875Speter#ifdef HAVE_ZOS_PTHREADS
184251875Speter        stat = errno;
185251875Speter#endif
186251875Speter
187251875Speter        return stat;
188251875Speter    }
189251875Speter}
190251875Speter
191251875SpeterAPR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
192251875Speter{
193251875Speter    return pthread_self();
194251875Speter}
195251875Speter
196251875SpeterAPR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1,
197251875Speter                                     apr_os_thread_t tid2)
198251875Speter{
199251875Speter    return pthread_equal(tid1, tid2);
200251875Speter}
201251875Speter
202251875SpeterAPR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd,
203251875Speter                                          apr_status_t retval)
204251875Speter{
205251875Speter    thd->exitval = retval;
206251875Speter    apr_pool_destroy(thd->pool);
207251875Speter    pthread_exit(NULL);
208251875Speter    return APR_SUCCESS;
209251875Speter}
210251875Speter
211251875SpeterAPR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval,
212251875Speter                                          apr_thread_t *thd)
213251875Speter{
214251875Speter    apr_status_t stat;
215251875Speter    apr_status_t *thread_stat;
216251875Speter
217251875Speter    if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) {
218251875Speter        *retval = thd->exitval;
219251875Speter        return APR_SUCCESS;
220251875Speter    }
221251875Speter    else {
222251875Speter#ifdef HAVE_ZOS_PTHREADS
223251875Speter        stat = errno;
224251875Speter#endif
225251875Speter
226251875Speter        return stat;
227251875Speter    }
228251875Speter}
229251875Speter
230251875SpeterAPR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
231251875Speter{
232251875Speter    apr_status_t stat;
233251875Speter
234251875Speter#ifdef HAVE_ZOS_PTHREADS
235251875Speter    if ((stat = pthread_detach(thd->td)) == 0) {
236251875Speter#else
237251875Speter    if ((stat = pthread_detach(*thd->td)) == 0) {
238251875Speter#endif
239251875Speter
240251875Speter        return APR_SUCCESS;
241251875Speter    }
242251875Speter    else {
243251875Speter#ifdef HAVE_ZOS_PTHREADS
244251875Speter        stat = errno;
245251875Speter#endif
246251875Speter
247251875Speter        return stat;
248251875Speter    }
249251875Speter}
250251875Speter
251251875SpeterAPR_DECLARE(void) apr_thread_yield(void)
252251875Speter{
253251875Speter#ifdef HAVE_PTHREAD_YIELD
254251875Speter#ifdef HAVE_ZOS_PTHREADS
255251875Speter    pthread_yield(NULL);
256251875Speter#else
257251875Speter    pthread_yield();
258251875Speter#endif /* HAVE_ZOS_PTHREADS */
259251875Speter#else
260251875Speter#ifdef HAVE_SCHED_YIELD
261251875Speter    sched_yield();
262251875Speter#endif
263251875Speter#endif
264251875Speter}
265251875Speter
266251875SpeterAPR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
267251875Speter                                              apr_thread_t *thread)
268251875Speter{
269251875Speter    return apr_pool_userdata_get(data, key, thread->pool);
270251875Speter}
271251875Speter
272251875SpeterAPR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
273251875Speter                              apr_status_t (*cleanup)(void *),
274251875Speter                              apr_thread_t *thread)
275251875Speter{
276251875Speter    return apr_pool_userdata_set(data, key, cleanup, thread->pool);
277251875Speter}
278251875Speter
279251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
280251875Speter                                            apr_thread_t *thd)
281251875Speter{
282251875Speter    *thethd = thd->td;
283251875Speter    return APR_SUCCESS;
284251875Speter}
285251875Speter
286251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
287251875Speter                                            apr_os_thread_t *thethd,
288251875Speter                                            apr_pool_t *pool)
289251875Speter{
290251875Speter    if (pool == NULL) {
291251875Speter        return APR_ENOPOOL;
292251875Speter    }
293251875Speter
294251875Speter    if ((*thd) == NULL) {
295251875Speter        (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
296251875Speter        (*thd)->pool = pool;
297251875Speter    }
298251875Speter
299251875Speter    (*thd)->td = thethd;
300251875Speter    return APR_SUCCESS;
301251875Speter}
302251875Speter
303251875SpeterAPR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
304251875Speter                                               apr_pool_t *p)
305251875Speter{
306251875Speter    static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
307251875Speter
308251875Speter    *control = apr_palloc(p, sizeof(**control));
309251875Speter    (*control)->once = once_init;
310251875Speter    return APR_SUCCESS;
311251875Speter}
312251875Speter
313251875SpeterAPR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
314251875Speter                                          void (*func)(void))
315251875Speter{
316251875Speter    return pthread_once(&control->once, func);
317251875Speter}
318251875Speter
319251875SpeterAPR_POOL_IMPLEMENT_ACCESSOR(thread)
320251875Speter
321251875Speter#endif  /* HAVE_PTHREAD_H */
322251875Speter#endif  /* APR_HAS_THREADS */
323251875Speter
324251875Speter#if !APR_HAS_THREADS
325251875Speter
326251875Speter/* avoid warning for no prototype */
327251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_get(void);
328251875Speter
329251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_get(void)
330251875Speter{
331251875Speter    return APR_ENOTIMPL;
332251875Speter}
333251875Speter
334251875Speter#endif
335