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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "apr_portable.h"
19 #include "apr_strings.h"
20 #include "apr_arch_threadproc.h"
22 static int thread_count = 0;
24 apr_status_t apr_threadattr_create(apr_threadattr_t **new,
27 (*new) = (apr_threadattr_t *)apr_palloc(pool,
28 sizeof(apr_threadattr_t));
35 (*new)->stack_size = APR_DEFAULT_STACK_SIZE;
37 (*new)->thread_name = NULL;
41 apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr,apr_int32_t on)
47 apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr)
49 if (attr->detach == 1)
54 APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
57 attr->stack_size = stacksize;
61 static void *dummy_worker(void *opaque)
63 apr_thread_t *thd = (apr_thread_t *)opaque;
64 return thd->func(thd, thd->data);
67 apr_status_t apr_thread_create(apr_thread_t **new,
68 apr_threadattr_t *attr,
69 apr_thread_start_t func,
74 long flags = NX_THR_BIND_CONTEXT;
75 char threadName[NX_MAX_OBJECT_NAME_LEN+1];
76 size_t stack_size = APR_DEFAULT_STACK_SIZE;
78 if (attr && attr->thread_name) {
79 strncpy (threadName, attr->thread_name, NX_MAX_OBJECT_NAME_LEN);
82 sprintf(threadName, "APR_thread %04ld", ++thread_count);
85 /* An original stack size of 0 will allow NXCreateThread() to
86 * assign a default system stack size. An original stack
87 * size of less than 0 will assign the APR default stack size.
88 * anything else will be taken as is.
90 if (attr && (attr->stack_size >= 0)) {
91 stack_size = attr->stack_size;
94 (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
103 (*new)->thread_name = (char*)apr_pstrdup(pool, threadName);
105 stat = apr_pool_create(&(*new)->pool, pool);
106 if (stat != APR_SUCCESS) {
110 if (attr && attr->detach) {
111 flags |= NX_THR_DETACHED;
114 (*new)->ctx = NXContextAlloc(
115 /* void(*start_routine)(void *arg)*/(void (*)(void *)) dummy_worker,
116 /* void *arg */ (*new),
117 /* int priority */ NX_PRIO_MED,
118 /* NXSize_t stackSize */ stack_size,
119 /* long flags */ NX_CTX_NORMAL,
120 /* int *error */ &stat);
123 stat = NXContextSetName(
124 /* NXContext_t ctx */ (*new)->ctx,
125 /* const char *name */ threadName);
127 stat = NXThreadCreate(
128 /* NXContext_t context */ (*new)->ctx,
129 /* long flags */ flags,
130 /* NXThreadId_t *thread_id */ &(*new)->td);
135 return(stat);// if error
138 apr_os_thread_t apr_os_thread_current()
140 return NXThreadGetId();
143 int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
145 return (tid1 == tid2);
148 void apr_thread_yield()
153 apr_status_t apr_thread_exit(apr_thread_t *thd,
156 thd->exitval = retval;
157 apr_pool_destroy(thd->pool);
162 apr_status_t apr_thread_join(apr_status_t *retval,
168 if ((stat = NXThreadJoin(thd->td, &dthr, NULL)) == 0) {
169 *retval = thd->exitval;
177 apr_status_t apr_thread_detach(apr_thread_t *thd)
182 apr_status_t apr_thread_data_get(void **data, const char *key,
183 apr_thread_t *thread)
185 if (thread != NULL) {
186 return apr_pool_userdata_get(data, key, thread->pool);
190 return APR_ENOTHREAD;
194 apr_status_t apr_thread_data_set(void *data, const char *key,
195 apr_status_t (*cleanup) (void *),
196 apr_thread_t *thread)
198 if (thread != NULL) {
199 return apr_pool_userdata_set(data, key, cleanup, thread->pool);
203 return APR_ENOTHREAD;
207 APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
211 return APR_ENOTHREAD;
213 *thethd = &(thd->td);
217 APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
218 apr_os_thread_t *thethd,
224 if ((*thd) == NULL) {
225 (*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
228 (*thd)->td = *thethd;
232 APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
235 (*control) = apr_pcalloc(p, sizeof(**control));
239 APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
242 if (!atomic_xchg(&control->value, 1)) {
248 APR_POOL_IMPLEMENT_ACCESSOR(thread)