1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#include "apr.h" 18251875Speter#include "apr_portable.h" 19251875Speter#include "apr_arch_threadproc.h" 20251875Speter 21251875Speter#if APR_HAS_THREADS 22251875Speter 23251875Speter#if APR_HAVE_PTHREAD_H 24251875Speter 25251875Speter/* Destroy the threadattr object */ 26251875Speterstatic apr_status_t threadattr_cleanup(void *data) 27251875Speter{ 28251875Speter apr_threadattr_t *attr = data; 29251875Speter apr_status_t rv; 30251875Speter 31251875Speter rv = pthread_attr_destroy(&attr->attr); 32251875Speter#ifdef HAVE_ZOS_PTHREADS 33251875Speter if (rv) { 34251875Speter rv = errno; 35251875Speter } 36251875Speter#endif 37251875Speter return rv; 38251875Speter} 39251875Speter 40251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, 41251875Speter apr_pool_t *pool) 42251875Speter{ 43251875Speter apr_status_t stat; 44251875Speter 45251875Speter (*new) = apr_palloc(pool, sizeof(apr_threadattr_t)); 46251875Speter (*new)->pool = pool; 47251875Speter stat = pthread_attr_init(&(*new)->attr); 48251875Speter 49251875Speter if (stat == 0) { 50251875Speter apr_pool_cleanup_register(pool, *new, threadattr_cleanup, 51251875Speter apr_pool_cleanup_null); 52251875Speter return APR_SUCCESS; 53251875Speter } 54251875Speter#ifdef HAVE_ZOS_PTHREADS 55251875Speter stat = errno; 56251875Speter#endif 57251875Speter 58251875Speter return stat; 59251875Speter} 60251875Speter 61251875Speter#if defined(PTHREAD_CREATE_DETACHED) 62251875Speter#define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE) 63251875Speter#else 64251875Speter#define DETACH_ARG(v) ((v) ? 1 : 0) 65251875Speter#endif 66251875Speter 67251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, 68251875Speter apr_int32_t on) 69251875Speter{ 70251875Speter apr_status_t stat; 71251875Speter#ifdef HAVE_ZOS_PTHREADS 72251875Speter int arg = DETACH_ARG(on); 73251875Speter 74251875Speter if ((stat = pthread_attr_setdetachstate(&attr->attr, &arg)) == 0) { 75251875Speter#else 76251875Speter if ((stat = pthread_attr_setdetachstate(&attr->attr, 77251875Speter DETACH_ARG(on))) == 0) { 78251875Speter#endif 79251875Speter return APR_SUCCESS; 80251875Speter } 81251875Speter else { 82251875Speter#ifdef HAVE_ZOS_PTHREADS 83251875Speter stat = errno; 84251875Speter#endif 85251875Speter 86251875Speter return stat; 87251875Speter } 88251875Speter} 89251875Speter 90251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr) 91251875Speter{ 92251875Speter int state; 93251875Speter 94251875Speter#ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG 95251875Speter state = pthread_attr_getdetachstate(&attr->attr); 96251875Speter#else 97251875Speter pthread_attr_getdetachstate(&attr->attr, &state); 98251875Speter#endif 99253734Speter if (state == DETACH_ARG(1)) 100251875Speter return APR_DETACH; 101251875Speter return APR_NOTDETACH; 102251875Speter} 103251875Speter 104251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, 105251875Speter apr_size_t stacksize) 106251875Speter{ 107251875Speter int stat; 108251875Speter 109251875Speter stat = pthread_attr_setstacksize(&attr->attr, stacksize); 110251875Speter if (stat == 0) { 111251875Speter return APR_SUCCESS; 112251875Speter } 113251875Speter#ifdef HAVE_ZOS_PTHREADS 114251875Speter stat = errno; 115251875Speter#endif 116251875Speter 117251875Speter return stat; 118251875Speter} 119251875Speter 120251875SpeterAPR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, 121251875Speter apr_size_t size) 122251875Speter{ 123251875Speter#ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE 124251875Speter apr_status_t rv; 125251875Speter 126251875Speter rv = pthread_attr_setguardsize(&attr->attr, size); 127251875Speter if (rv == 0) { 128251875Speter return APR_SUCCESS; 129251875Speter } 130251875Speter#ifdef HAVE_ZOS_PTHREADS 131251875Speter rv = errno; 132251875Speter#endif 133251875Speter return rv; 134251875Speter#else 135251875Speter return APR_ENOTIMPL; 136251875Speter#endif 137251875Speter} 138251875Speter 139251875Speterstatic void *dummy_worker(void *opaque) 140251875Speter{ 141251875Speter apr_thread_t *thread = (apr_thread_t*)opaque; 142251875Speter return thread->func(thread, thread->data); 143251875Speter} 144251875Speter 145251875SpeterAPR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, 146251875Speter apr_threadattr_t *attr, 147251875Speter apr_thread_start_t func, 148251875Speter void *data, 149251875Speter apr_pool_t *pool) 150251875Speter{ 151251875Speter apr_status_t stat; 152251875Speter pthread_attr_t *temp; 153251875Speter 154251875Speter (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); 155251875Speter 156251875Speter if ((*new) == NULL) { 157251875Speter return APR_ENOMEM; 158251875Speter } 159251875Speter 160251875Speter (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t)); 161251875Speter 162251875Speter if ((*new)->td == NULL) { 163251875Speter return APR_ENOMEM; 164251875Speter } 165251875Speter 166251875Speter (*new)->data = data; 167251875Speter (*new)->func = func; 168251875Speter 169251875Speter if (attr) 170251875Speter temp = &attr->attr; 171251875Speter else 172251875Speter temp = NULL; 173251875Speter 174251875Speter stat = apr_pool_create(&(*new)->pool, pool); 175251875Speter if (stat != APR_SUCCESS) { 176251875Speter return stat; 177251875Speter } 178251875Speter 179251875Speter if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { 180251875Speter return APR_SUCCESS; 181251875Speter } 182251875Speter else { 183251875Speter#ifdef HAVE_ZOS_PTHREADS 184251875Speter stat = errno; 185251875Speter#endif 186251875Speter 187251875Speter return stat; 188251875Speter } 189251875Speter} 190251875Speter 191251875SpeterAPR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) 192251875Speter{ 193251875Speter return pthread_self(); 194251875Speter} 195251875Speter 196251875SpeterAPR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1, 197251875Speter apr_os_thread_t tid2) 198251875Speter{ 199251875Speter return pthread_equal(tid1, tid2); 200251875Speter} 201251875Speter 202251875SpeterAPR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, 203251875Speter apr_status_t retval) 204251875Speter{ 205251875Speter thd->exitval = retval; 206251875Speter apr_pool_destroy(thd->pool); 207251875Speter pthread_exit(NULL); 208251875Speter return APR_SUCCESS; 209251875Speter} 210251875Speter 211251875SpeterAPR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, 212251875Speter apr_thread_t *thd) 213251875Speter{ 214251875Speter apr_status_t stat; 215251875Speter apr_status_t *thread_stat; 216251875Speter 217251875Speter if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) { 218251875Speter *retval = thd->exitval; 219251875Speter return APR_SUCCESS; 220251875Speter } 221251875Speter else { 222251875Speter#ifdef HAVE_ZOS_PTHREADS 223251875Speter stat = errno; 224251875Speter#endif 225251875Speter 226251875Speter return stat; 227251875Speter } 228251875Speter} 229251875Speter 230251875SpeterAPR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) 231251875Speter{ 232251875Speter apr_status_t stat; 233251875Speter 234251875Speter#ifdef HAVE_ZOS_PTHREADS 235251875Speter if ((stat = pthread_detach(thd->td)) == 0) { 236251875Speter#else 237251875Speter if ((stat = pthread_detach(*thd->td)) == 0) { 238251875Speter#endif 239251875Speter 240251875Speter return APR_SUCCESS; 241251875Speter } 242251875Speter else { 243251875Speter#ifdef HAVE_ZOS_PTHREADS 244251875Speter stat = errno; 245251875Speter#endif 246251875Speter 247251875Speter return stat; 248251875Speter } 249251875Speter} 250251875Speter 251251875SpeterAPR_DECLARE(void) apr_thread_yield(void) 252251875Speter{ 253251875Speter#ifdef HAVE_PTHREAD_YIELD 254251875Speter#ifdef HAVE_ZOS_PTHREADS 255251875Speter pthread_yield(NULL); 256251875Speter#else 257251875Speter pthread_yield(); 258251875Speter#endif /* HAVE_ZOS_PTHREADS */ 259251875Speter#else 260251875Speter#ifdef HAVE_SCHED_YIELD 261251875Speter sched_yield(); 262251875Speter#endif 263251875Speter#endif 264251875Speter} 265251875Speter 266251875SpeterAPR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, 267251875Speter apr_thread_t *thread) 268251875Speter{ 269251875Speter return apr_pool_userdata_get(data, key, thread->pool); 270251875Speter} 271251875Speter 272251875SpeterAPR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, 273251875Speter apr_status_t (*cleanup)(void *), 274251875Speter apr_thread_t *thread) 275251875Speter{ 276251875Speter return apr_pool_userdata_set(data, key, cleanup, thread->pool); 277251875Speter} 278251875Speter 279251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, 280251875Speter apr_thread_t *thd) 281251875Speter{ 282251875Speter *thethd = thd->td; 283251875Speter return APR_SUCCESS; 284251875Speter} 285251875Speter 286251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, 287251875Speter apr_os_thread_t *thethd, 288251875Speter apr_pool_t *pool) 289251875Speter{ 290251875Speter if (pool == NULL) { 291251875Speter return APR_ENOPOOL; 292251875Speter } 293251875Speter 294251875Speter if ((*thd) == NULL) { 295251875Speter (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); 296251875Speter (*thd)->pool = pool; 297251875Speter } 298251875Speter 299251875Speter (*thd)->td = thethd; 300251875Speter return APR_SUCCESS; 301251875Speter} 302251875Speter 303251875SpeterAPR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, 304251875Speter apr_pool_t *p) 305251875Speter{ 306251875Speter static const pthread_once_t once_init = PTHREAD_ONCE_INIT; 307251875Speter 308251875Speter *control = apr_palloc(p, sizeof(**control)); 309251875Speter (*control)->once = once_init; 310251875Speter return APR_SUCCESS; 311251875Speter} 312251875Speter 313251875SpeterAPR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, 314251875Speter void (*func)(void)) 315251875Speter{ 316251875Speter return pthread_once(&control->once, func); 317251875Speter} 318251875Speter 319251875SpeterAPR_POOL_IMPLEMENT_ACCESSOR(thread) 320251875Speter 321251875Speter#endif /* HAVE_PTHREAD_H */ 322251875Speter#endif /* APR_HAS_THREADS */ 323251875Speter 324251875Speter#if !APR_HAS_THREADS 325251875Speter 326251875Speter/* avoid warning for no prototype */ 327251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_get(void); 328251875Speter 329251875SpeterAPR_DECLARE(apr_status_t) apr_os_thread_get(void) 330251875Speter{ 331251875Speter return APR_ENOTIMPL; 332251875Speter} 333251875Speter 334251875Speter#endif 335