xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/threadproc/beos/thread.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 
apr_threadattr_create(apr_threadattr_t ** new,apr_pool_t * pool)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 
apr_threadattr_detach_set(apr_threadattr_t * attr,apr_int32_t on)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 
apr_threadattr_detach_get(apr_threadattr_t * attr)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 
apr_threadattr_stacksize_set(apr_threadattr_t * attr,apr_size_t stacksize)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 
apr_threadattr_guardsize_set(apr_threadattr_t * attr,apr_size_t size)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 
dummy_worker(void * opaque)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 
apr_thread_create(apr_thread_t ** new,apr_threadattr_t * attr,apr_thread_start_t func,void * data,apr_pool_t * pool)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 
apr_os_thread_current(void)112 APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
113 {
114     return find_thread(NULL);
115 }
116 
apr_os_thread_equal(apr_os_thread_t tid1,apr_os_thread_t tid2)117 int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
118 {
119     return tid1 == tid2;
120 }
121 
apr_thread_exit(apr_thread_t * thd,apr_status_t retval)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 
apr_thread_join(apr_status_t * retval,apr_thread_t * thd)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 
apr_thread_detach(apr_thread_t * thd)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 
apr_thread_yield()161 void apr_thread_yield()
162 {
163 }
164 
apr_thread_data_get(void ** data,const char * key,apr_thread_t * thread)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 
apr_thread_data_set(void * data,const char * key,apr_status_t (* cleanup)(void *),apr_thread_t * thread)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 
apr_os_thread_get(apr_os_thread_t ** thethd,apr_thread_t * thd)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 
apr_os_thread_put(apr_thread_t ** thd,apr_os_thread_t * thethd,apr_pool_t * pool)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 
thread_once_cleanup(void * vcontrol)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 
apr_thread_once_init(apr_thread_once_t ** control,apr_pool_t * p)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 
apr_thread_once(apr_thread_once_t * control,void (* func)(void))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)
238