bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / threadproc / os2 / 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 #define INCL_DOSERRORS
18 #define INCL_DOS
19 #include "apr_arch_threadproc.h"
20 #include "apr_thread_proc.h"
21 #include "apr_general.h"
22 #include "apr_lib.h"
23 #include "apr_portable.h"
24 #include "apr_arch_file_io.h"
25 #include <stdlib.h>
26
27 APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
28 {
29     (*new) = (apr_threadattr_t *)apr_palloc(pool, sizeof(apr_threadattr_t));
30
31     if ((*new) == NULL) {
32         return APR_ENOMEM;
33     }
34
35     (*new)->pool = pool;
36     (*new)->attr = 0;
37     (*new)->stacksize = 0;
38     return APR_SUCCESS;
39 }
40
41
42
43 APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
44 {
45     attr->attr |= APR_THREADATTR_DETACHED;
46     return APR_SUCCESS;
47 }
48
49
50
51 APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
52 {
53     return (attr->attr & APR_THREADATTR_DETACHED) ? APR_DETACH : APR_NOTDETACH;
54 }
55
56
57
58 APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
59                                                        apr_size_t stacksize)
60 {
61     attr->stacksize = stacksize;
62     return APR_SUCCESS;
63 }
64
65
66
67 static void apr_thread_begin(void *arg)
68 {
69   apr_thread_t *thread = (apr_thread_t *)arg;
70   thread->exitval = thread->func(thread, thread->data);
71 }
72
73
74
75 APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, 
76                                             apr_thread_start_t func, void *data, 
77                                             apr_pool_t *pool)
78 {
79     apr_status_t stat;
80     apr_thread_t *thread;
81  
82     thread = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
83     *new = thread;
84
85     if (thread == NULL) {
86         return APR_ENOMEM;
87     }
88
89     thread->pool = pool;
90     thread->attr = attr;
91     thread->func = func;
92     thread->data = data;
93     stat = apr_pool_create(&thread->pool, pool);
94     
95     if (stat != APR_SUCCESS) {
96         return stat;
97     }
98
99     if (attr == NULL) {
100         stat = apr_threadattr_create(&thread->attr, thread->pool);
101         
102         if (stat != APR_SUCCESS) {
103             return stat;
104         }
105     }
106
107     thread->tid = _beginthread(apr_thread_begin, NULL,
108                                thread->attr->stacksize > 0 ?
109                                thread->attr->stacksize : APR_THREAD_STACKSIZE,
110                                thread);
111         
112     if (thread->tid < 0) {
113         return errno;
114     }
115
116     return APR_SUCCESS;
117 }
118
119
120
121 APR_DECLARE(apr_os_thread_t) apr_os_thread_current()
122 {
123     PIB *ppib;
124     TIB *ptib;
125     DosGetInfoBlocks(&ptib, &ppib);
126     return ptib->tib_ptib2->tib2_ultid;
127 }
128
129
130
131 APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
132 {
133     thd->exitval = retval;
134     _endthread();
135     return -1; /* If we get here something's wrong */
136 }
137
138
139
140 APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
141 {
142     ULONG rc;
143     TID waittid = thd->tid;
144
145     if (thd->attr->attr & APR_THREADATTR_DETACHED)
146         return APR_EINVAL;
147
148     rc = DosWaitThread(&waittid, DCWW_WAIT);
149
150     if (rc == ERROR_INVALID_THREADID)
151         rc = 0; /* Thread had already terminated */
152
153     *retval = thd->exitval;
154     return APR_OS2_STATUS(rc);
155 }
156
157
158
159 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
160 {
161     thd->attr->attr |= APR_THREADATTR_DETACHED;
162     return APR_SUCCESS;
163 }
164
165
166
167 void apr_thread_yield()
168 {
169     DosSleep(0);
170 }
171
172
173
174 APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, apr_thread_t *thd)
175 {
176     *thethd = &thd->tid;
177     return APR_SUCCESS;
178 }
179
180
181
182 APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, apr_os_thread_t *thethd, 
183                                             apr_pool_t *pool)
184 {
185     if ((*thd) == NULL) {
186         (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
187         (*thd)->pool = pool;
188     }
189     (*thd)->tid = *thethd;
190     return APR_SUCCESS;
191 }
192
193
194
195 int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
196 {
197     return tid1 == tid2;
198 }
199
200
201
202 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread)
203 {
204     return apr_pool_userdata_get(data, key, thread->pool);
205 }
206
207
208
209 APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
210                                               apr_status_t (*cleanup) (void *),
211                                               apr_thread_t *thread)
212 {
213     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
214 }
215
216 APR_POOL_IMPLEMENT_ACCESSOR(thread)
217
218
219
220 static apr_status_t thread_once_cleanup(void *vcontrol)
221 {
222     apr_thread_once_t *control = (apr_thread_once_t *)vcontrol;
223
224     if (control->sem) {
225         DosCloseEventSem(control->sem);
226     }
227
228     return APR_SUCCESS;
229 }
230
231
232
233 APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
234                                                apr_pool_t *p)
235 {
236     ULONG rc;
237     *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t));
238     rc = DosCreateEventSem(NULL, &(*control)->sem, 0, TRUE);
239     apr_pool_cleanup_register(p, control, thread_once_cleanup, apr_pool_cleanup_null);
240     return APR_FROM_OS_ERROR(rc);
241 }
242
243
244
245 APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, 
246                                           void (*func)(void))
247 {
248     if (!control->hit) {
249         ULONG count, rc;
250         rc = DosResetEventSem(control->sem, &count);
251
252         if (rc == 0 && count) {
253             control->hit = 1;
254             func();
255         }
256     }
257
258     return APR_SUCCESS;
259 }