1/* thr_posix.c - wrapper around posix and posixish thread implementations. */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 17#include "portable.h" 18 19#if defined( HAVE_PTHREADS ) 20 21#include <ac/errno.h> 22 23#ifdef REPLACE_BROKEN_YIELD 24#ifndef HAVE_NANOSLEEP 25#include <ac/socket.h> 26#endif 27#include <ac/time.h> 28#endif 29 30#include "ldap_pvt_thread.h" /* Get the thread interface */ 31#define LDAP_THREAD_IMPLEMENTATION 32#define LDAP_THREAD_RDWR_IMPLEMENTATION 33#include "ldap_thr_debug.h" /* May rename the symbols defined below */ 34#include <signal.h> /* For pthread_kill() */ 35 36#if HAVE_PTHREADS < 6 37# define LDAP_INT_THREAD_ATTR_DEFAULT pthread_attr_default 38# define LDAP_INT_THREAD_CONDATTR_DEFAULT pthread_condattr_default 39# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default 40#else 41# define LDAP_INT_THREAD_ATTR_DEFAULT NULL 42# define LDAP_INT_THREAD_CONDATTR_DEFAULT NULL 43# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL 44#endif 45 46#ifdef LDAP_THREAD_DEBUG 47# if defined LDAP_INT_THREAD_MUTEXATTR /* May be defined in CPPFLAGS */ 48# elif defined HAVE_PTHREAD_KILL_OTHER_THREADS_NP 49 /* LinuxThreads hack */ 50# define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK_NP 51# else 52# define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK 53# endif 54static pthread_mutexattr_t mutex_attr; 55# undef LDAP_INT_THREAD_MUTEXATTR_DEFAULT 56# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr 57#endif 58 59#if HAVE_PTHREADS < 7 60#define ERRVAL(val) ((val) < 0 ? errno : 0) 61#else 62#define ERRVAL(val) (val) 63#endif 64 65int 66ldap_int_thread_initialize( void ) 67{ 68#ifdef LDAP_INT_THREAD_MUTEXATTR 69 pthread_mutexattr_init( &mutex_attr ); 70 pthread_mutexattr_settype( &mutex_attr, LDAP_INT_THREAD_MUTEXATTR ); 71#endif 72 return 0; 73} 74 75int 76ldap_int_thread_destroy( void ) 77{ 78#ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP 79 /* LinuxThreads: kill clones */ 80 pthread_kill_other_threads_np(); 81#endif 82#ifdef LDAP_INT_THREAD_MUTEXATTR 83 pthread_mutexattr_destroy( &mutex_attr ); 84#endif 85 return 0; 86} 87 88#ifdef LDAP_THREAD_HAVE_SETCONCURRENCY 89int 90ldap_pvt_thread_set_concurrency(int n) 91{ 92#ifdef HAVE_PTHREAD_SETCONCURRENCY 93 return pthread_setconcurrency( n ); 94#elif defined(HAVE_THR_SETCONCURRENCY) 95 return thr_setconcurrency( n ); 96#else 97 return 0; 98#endif 99} 100#endif 101 102#ifdef LDAP_THREAD_HAVE_GETCONCURRENCY 103int 104ldap_pvt_thread_get_concurrency(void) 105{ 106#ifdef HAVE_PTHREAD_GETCONCURRENCY 107 return pthread_getconcurrency(); 108#elif defined(HAVE_THR_GETCONCURRENCY) 109 return thr_getconcurrency(); 110#else 111 return 0; 112#endif 113} 114#endif 115 116/* detachstate appeared in Draft 6, but without manifest constants. 117 * in Draft 7 they were called PTHREAD_CREATE_UNDETACHED and ...DETACHED. 118 * in Draft 8 on, ...UNDETACHED became ...JOINABLE. 119 */ 120#ifndef PTHREAD_CREATE_JOINABLE 121#ifdef PTHREAD_CREATE_UNDETACHED 122#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED 123#else 124#define PTHREAD_CREATE_JOINABLE 0 125#endif 126#endif 127 128#ifndef PTHREAD_CREATE_DETACHED 129#define PTHREAD_CREATE_DETACHED 1 130#endif 131 132int 133ldap_pvt_thread_create( ldap_pvt_thread_t * thread, 134 int detach, 135 void *(*start_routine)( void * ), 136 void *arg) 137{ 138 int rtn; 139 pthread_attr_t attr; 140 141/* Always create the thread attrs, so we can set stacksize if we need to */ 142#if HAVE_PTHREADS > 5 143 pthread_attr_init(&attr); 144#else 145 pthread_attr_create(&attr); 146#endif 147 148#ifdef LDAP_PVT_THREAD_SET_STACK_SIZE 149 /* this should be tunable */ 150 pthread_attr_setstacksize( &attr, LDAP_PVT_THREAD_STACK_SIZE ); 151#endif 152 153#if HAVE_PTHREADS > 5 154 detach = detach ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE; 155#if HAVE_PTHREADS == 6 156 pthread_attr_setdetachstate(&attr, &detach); 157#else 158 pthread_attr_setdetachstate(&attr, detach); 159#endif 160#endif 161 162#if HAVE_PTHREADS < 5 163 rtn = pthread_create( thread, attr, start_routine, arg ); 164#else 165 rtn = pthread_create( thread, &attr, start_routine, arg ); 166#endif 167 168#if HAVE_PTHREADS > 5 169 pthread_attr_destroy(&attr); 170#else 171 pthread_attr_delete(&attr); 172 if( detach ) { 173 pthread_detach( thread ); 174 } 175#endif 176 177#if HAVE_PTHREADS < 7 178 if ( rtn < 0 ) rtn = errno; 179#endif 180 return rtn; 181} 182 183void 184ldap_pvt_thread_exit( void *retval ) 185{ 186 pthread_exit( retval ); 187} 188 189int 190ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) 191{ 192#if HAVE_PTHREADS < 7 193 void *dummy; 194 if (thread_return==NULL) 195 thread_return=&dummy; 196#endif 197 return ERRVAL( pthread_join( thread, thread_return ) ); 198} 199 200int 201ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) 202{ 203#if defined(HAVE_PTHREAD_KILL) && HAVE_PTHREADS > 4 204 /* MacOS 10.1 is detected as v10 but has no pthread_kill() */ 205 return ERRVAL( pthread_kill( thread, signo ) ); 206#else 207 /* pthread package with DCE */ 208 if (kill( getpid(), signo )<0) 209 return errno; 210 return 0; 211#endif 212} 213 214int 215ldap_pvt_thread_yield( void ) 216{ 217#ifdef REPLACE_BROKEN_YIELD 218#ifdef HAVE_NANOSLEEP 219 struct timespec t = { 0, 0 }; 220 nanosleep(&t, NULL); 221#else 222 struct timeval tv = {0,0}; 223 select( 0, NULL, NULL, NULL, &tv ); 224#endif 225 return 0; 226 227#elif defined(HAVE_THR_YIELD) 228 thr_yield(); 229 return 0; 230 231#elif HAVE_PTHREADS == 10 232 return sched_yield(); 233 234#elif defined(_POSIX_THREAD_IS_GNU_PTH) 235 sched_yield(); 236 return 0; 237 238#elif HAVE_PTHREADS == 6 239 pthread_yield(NULL); 240 return 0; 241 242#else 243 pthread_yield(); 244 return 0; 245#endif 246} 247 248int 249ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) 250{ 251 return ERRVAL( pthread_cond_init( 252 cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) ); 253} 254 255int 256ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond ) 257{ 258 return ERRVAL( pthread_cond_destroy( cond ) ); 259} 260 261int 262ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) 263{ 264 return ERRVAL( pthread_cond_signal( cond ) ); 265} 266 267int 268ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) 269{ 270 return ERRVAL( pthread_cond_broadcast( cond ) ); 271} 272 273int 274ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, 275 ldap_pvt_thread_mutex_t *mutex ) 276{ 277 return ERRVAL( pthread_cond_wait( cond, mutex ) ); 278} 279 280int 281ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) 282{ 283 return ERRVAL( pthread_mutex_init( 284 mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ) ); 285} 286 287int 288ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) 289{ 290 return ERRVAL( pthread_mutex_destroy( mutex ) ); 291} 292 293int 294ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) 295{ 296 return ERRVAL( pthread_mutex_lock( mutex ) ); 297} 298 299int 300ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) 301{ 302 return ERRVAL( pthread_mutex_trylock( mutex ) ); 303} 304 305int 306ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) 307{ 308 return ERRVAL( pthread_mutex_unlock( mutex ) ); 309} 310 311ldap_pvt_thread_t ldap_pvt_thread_self( void ) 312{ 313 return pthread_self(); 314} 315 316int 317ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key ) 318{ 319 return pthread_key_create( key, NULL ); 320} 321 322int 323ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) 324{ 325 return pthread_key_delete( key ); 326} 327 328int 329ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) 330{ 331 return pthread_setspecific( key, data ); 332} 333 334int 335ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) 336{ 337 *data = pthread_getspecific( key ); 338 return 0; 339} 340 341#ifdef LDAP_THREAD_HAVE_RDWR 342#ifdef HAVE_PTHREAD_RWLOCK_DESTROY 343int 344ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) 345{ 346 return ERRVAL( pthread_rwlock_init( rw, NULL ) ); 347} 348 349int 350ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) 351{ 352 return ERRVAL( pthread_rwlock_destroy( rw ) ); 353} 354 355int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) 356{ 357 return ERRVAL( pthread_rwlock_rdlock( rw ) ); 358} 359 360int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) 361{ 362 return ERRVAL( pthread_rwlock_tryrdlock( rw ) ); 363} 364 365int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) 366{ 367 return ERRVAL( pthread_rwlock_unlock( rw ) ); 368} 369 370int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) 371{ 372 return ERRVAL( pthread_rwlock_wrlock( rw ) ); 373} 374 375int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) 376{ 377 return ERRVAL( pthread_rwlock_trywrlock( rw ) ); 378} 379 380int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) 381{ 382 return ERRVAL( pthread_rwlock_unlock( rw ) ); 383} 384 385#endif /* HAVE_PTHREAD_RWLOCK_DESTROY */ 386#endif /* LDAP_THREAD_HAVE_RDWR */ 387#endif /* HAVE_PTHREADS */ 388 389