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