upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / 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 APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new,
25                                                 apr_pool_t *pool)
26 {
27     apr_status_t stat;
28
29     (*new) = (apr_threadattr_t *)apr_pcalloc(pool, sizeof(apr_threadattr_t));
30     (*new)->attr = (pthread_attr_t *)apr_pcalloc(pool, sizeof(pthread_attr_t));
31
32     if ((*new) == NULL || (*new)->attr == NULL) {
33         return APR_ENOMEM;
34     }
35
36     (*new)->pool = pool;
37     stat = pthread_attr_init((*new)->attr);
38
39     if (stat == 0) {
40         return APR_SUCCESS;
41     }
42 #ifdef PTHREAD_SETS_ERRNO
43     stat = errno;
44 #endif
45
46     return stat;
47 }
48
49 APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr,
50                                                     apr_int32_t on)
51 {
52     apr_status_t stat;
53 #ifdef PTHREAD_ATTR_SETDETACHSTATE_ARG2_ADDR
54     int arg = on;
55
56     if ((stat = pthread_attr_setdetachstate(attr->attr, &arg)) == 0) {
57 #else
58     if ((stat = pthread_attr_setdetachstate(attr->attr, on)) == 0) {
59 #endif
60
61         return APR_SUCCESS;
62     }
63     else {
64 #ifdef PTHREAD_SETS_ERRNO
65         stat = errno;
66 #endif
67
68         return stat;
69     }
70 }
71
72 APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
73 {
74     int state;
75
76 #ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG
77     state = pthread_attr_getdetachstate(attr->attr);
78 #else
79     pthread_attr_getdetachstate(attr->attr, &state);
80 #endif
81     if (state == 1)
82         return APR_DETACH;
83     return APR_NOTDETACH;
84 }
85
86 APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
87                                                        apr_size_t stacksize)
88 {
89     int stat;
90
91     stat = pthread_attr_setstacksize(attr->attr, stacksize);
92     if (stat == 0) {
93         return APR_SUCCESS;
94     }
95 #ifdef PTHREAD_SETS_ERRNO
96     stat = errno;
97 #endif
98
99     return stat;
100 }
101
102 static void *dummy_worker(void *opaque)
103 {
104     apr_thread_t *thread = (apr_thread_t*)opaque;
105     return thread->func(thread, thread->data);
106 }
107
108 APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
109                                             apr_threadattr_t *attr,
110                                             apr_thread_start_t func,
111                                             void *data,
112                                             apr_pool_t *pool)
113 {
114     apr_status_t stat;
115     pthread_attr_t *temp;
116
117     (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
118
119     if ((*new) == NULL) {
120         return APR_ENOMEM;
121     }
122
123     (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t));
124
125     if ((*new)->td == NULL) {
126         return APR_ENOMEM;
127     }
128
129     (*new)->pool = pool;
130     (*new)->data = data;
131     (*new)->func = func;
132
133     if (attr)
134         temp = attr->attr;
135     else
136         temp = NULL;
137
138     stat = apr_pool_create(&(*new)->pool, pool);
139     if (stat != APR_SUCCESS) {
140         return stat;
141     }
142
143     if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) {
144         return APR_SUCCESS;
145     }
146     else {
147 #ifdef PTHREAD_SETS_ERRNO
148         stat = errno;
149 #endif
150
151         return stat;
152     }
153 }
154
155 APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
156 {
157     return pthread_self();
158 }
159
160 APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1,
161                                      apr_os_thread_t tid2)
162 {
163     return pthread_equal(tid1, tid2);
164 }
165
166 APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd,
167                                           apr_status_t retval)
168 {
169     thd->exitval = retval;
170     apr_pool_destroy(thd->pool);
171     pthread_exit(NULL);
172     return APR_SUCCESS;
173 }
174
175 APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval,
176                                           apr_thread_t *thd)
177 {
178     apr_status_t stat;
179     apr_status_t *thread_stat;
180
181     if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) {
182         *retval = thd->exitval;
183         return APR_SUCCESS;
184     }
185     else {
186 #ifdef PTHREAD_SETS_ERRNO
187         stat = errno;
188 #endif
189
190         return stat;
191     }
192 }
193
194 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
195 {
196     apr_status_t stat;
197
198 #ifdef PTHREAD_DETACH_ARG1_ADDR
199     if ((stat = pthread_detach(thd->td)) == 0) {
200 #else
201     if ((stat = pthread_detach(*thd->td)) == 0) {
202 #endif
203
204         return APR_SUCCESS;
205     }
206     else {
207 #ifdef PTHREAD_SETS_ERRNO
208         stat = errno;
209 #endif
210
211         return stat;
212     }
213 }
214
215 void apr_thread_yield()
216 {
217 }
218
219 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
220                                               apr_thread_t *thread)
221 {
222     return apr_pool_userdata_get(data, key, thread->pool);
223 }
224
225 APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
226                               apr_status_t (*cleanup)(void *),
227                               apr_thread_t *thread)
228 {
229     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
230 }
231
232 APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
233                                             apr_thread_t *thd)
234 {
235     *thethd = thd->td;
236     return APR_SUCCESS;
237 }
238
239 APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
240                                             apr_os_thread_t *thethd,
241                                             apr_pool_t *pool)
242 {
243     if (pool == NULL) {
244         return APR_ENOPOOL;
245     }
246
247     if ((*thd) == NULL) {
248         (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
249         (*thd)->pool = pool;
250     }
251
252     (*thd)->td = thethd;
253     return APR_SUCCESS;
254 }
255
256 APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
257                                                apr_pool_t *p)
258 {
259     static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
260
261     *control = apr_palloc(p, sizeof(**control));
262     (*control)->once = once_init;
263     return APR_SUCCESS;
264 }
265
266 APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
267                                           void (*func)(void))
268 {
269     return pthread_once(&control->once, func);
270 }
271
272 APR_POOL_IMPLEMENT_ACCESSOR(thread)
273
274 #endif  /* HAVE_PTHREAD_H */
275 #endif  /* APR_HAS_THREADS */
276
277 #if !APR_HAS_THREADS
278
279 /* avoid warning for no prototype */
280 APR_DECLARE(apr_status_t) apr_os_thread_get(void);
281
282 APR_DECLARE(apr_status_t) apr_os_thread_get(void)
283 {
284     return APR_ENOTIMPL;
285 }
286
287 #endif