Initial import.
[profile/ivi/apr.git] / threadproc / beos / 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_arch_threadproc.h"
18 #include "apr_portable.h"
19
20 APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
21 {
22     (*new) = (apr_threadattr_t *)apr_palloc(pool, 
23               sizeof(apr_threadattr_t));
24
25     if ((*new) == NULL) {
26         return APR_ENOMEM;
27     }
28
29     (*new)->pool = pool;
30         (*new)->attr = (int32)B_NORMAL_PRIORITY;
31
32     return APR_SUCCESS;
33 }
34
35 APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
36 {
37         if (on == 1){
38                 attr->detached = 1;
39         } else {
40                 attr->detached = 0;
41         }    
42     return APR_SUCCESS;
43 }
44
45 APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
46 {
47         if (attr->detached == 1){
48                 return APR_DETACH;
49         }
50         return APR_NOTDETACH;
51 }
52
53 APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
54                                                        apr_size_t stacksize)
55 {
56     return APR_ENOTIMPL;
57 }
58
59 APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
60                                                        apr_size_t size)
61 {
62     return APR_ENOTIMPL;
63 }
64
65 static void *dummy_worker(void *opaque)
66 {
67     apr_thread_t *thd = (apr_thread_t*)opaque;
68     return thd->func(thd, thd->data);
69 }
70
71 APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr,
72                                             apr_thread_start_t func, void *data,
73                                             apr_pool_t *pool)
74 {
75     int32 temp;
76     apr_status_t stat;
77     
78     (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
79     if ((*new) == NULL) {
80         return APR_ENOMEM;
81     }
82
83     (*new)->data = data;
84     (*new)->func = func;
85     (*new)->exitval = -1;
86
87     /* First we create the new thread...*/
88         if (attr)
89             temp = attr->attr;
90         else
91             temp = B_NORMAL_PRIORITY;
92
93     stat = apr_pool_create(&(*new)->pool, pool);
94     if (stat != APR_SUCCESS) {
95         return stat;
96     }
97
98     (*new)->td = spawn_thread((thread_func)dummy_worker, 
99                               "apr thread", 
100                               temp, 
101                               (*new));
102
103     /* Now we try to run it...*/
104     if (resume_thread((*new)->td) == B_NO_ERROR) {
105         return APR_SUCCESS;
106     }
107     else {
108         return errno;
109     } 
110 }
111
112 APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
113 {
114     return find_thread(NULL);
115 }
116
117 int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
118 {
119     return tid1 == tid2;
120 }
121
122 APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
123 {
124     apr_pool_destroy(thd->pool);
125     thd->exitval = retval;
126     exit_thread ((status_t)(retval));
127     /* This will never be reached... */
128     return APR_SUCCESS;
129 }
130
131 APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
132 {
133     status_t rv = 0, ret;
134     ret = wait_for_thread(thd->td, &rv);
135     if (ret == B_NO_ERROR) {
136         *retval = rv;
137         return APR_SUCCESS;
138     }
139     else {
140         /* if we've missed the thread's death, did we set an exit value prior
141          * to it's demise?  If we did return that.
142          */
143         if (thd->exitval != -1) {
144             *retval = thd->exitval;
145             return APR_SUCCESS;
146         } else 
147             return ret;
148     }
149 }
150
151 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
152 {
153         if (suspend_thread(thd->td) == B_NO_ERROR){
154         return APR_SUCCESS;
155     }
156     else {
157         return errno;
158     }
159 }
160
161 void apr_thread_yield()
162 {
163 }
164
165 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread)
166 {
167     return apr_pool_userdata_get(data, key, thread->pool);
168 }
169
170 APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
171                                               apr_status_t (*cleanup) (void *),
172                                               apr_thread_t *thread)
173 {
174     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
175 }
176
177 APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, apr_thread_t *thd)
178 {
179     *thethd = &thd->td;
180     return APR_SUCCESS;
181 }
182
183 APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, apr_os_thread_t *thethd, 
184                                             apr_pool_t *pool)
185 {
186     if (pool == NULL) {
187         return APR_ENOPOOL;
188     }
189     if ((*thd) == NULL) {
190         (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
191         (*thd)->pool = pool;
192     }
193     (*thd)->td = *thethd;
194     return APR_SUCCESS;
195 }
196
197 static apr_status_t thread_once_cleanup(void *vcontrol)
198 {
199     apr_thread_once_t *control = (apr_thread_once_t *)vcontrol;
200
201     if (control->sem) {
202         release_sem(control->sem);
203         delete_sem(control->sem);
204     }
205
206     return APR_SUCCESS;
207 }
208
209 APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
210                                                apr_pool_t *p)
211 {
212     int rc;
213     *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t));
214     (*control)->hit = 0; /* we haven't done it yet... */
215     rc = ((*control)->sem = create_sem(1, "thread_once"));
216     if (rc < 0)
217         return rc;
218
219     apr_pool_cleanup_register(p, control, thread_once_cleanup, apr_pool_cleanup_null);
220     return APR_SUCCESS;
221 }
222
223
224
225 APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, 
226                                           void (*func)(void))
227 {
228     if (!control->hit) {
229         if (acquire_sem(control->sem) == B_OK) {
230             control->hit = 1;
231             func();
232         }
233     }
234     return APR_SUCCESS;
235 }
236
237 APR_POOL_IMPLEMENT_ACCESSOR(thread)