thr_posix.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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-2022 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. #include "portable.h"
  17. #if defined( HAVE_PTHREADS )
  18. #ifdef __GLIBC__
  19. #undef _FEATURES_H
  20. #define _XOPEN_SOURCE 500 /* For pthread_setconcurrency() on glibc */
  21. #endif
  22. #include <ac/errno.h>
  23. #ifdef REPLACE_BROKEN_YIELD
  24. #ifndef HAVE_NANOSLEEP
  25. #include <ac/socket.h>
  26. #endif
  27. #include <ac/time.h>
  28. #endif
  29. #include "ldap_pvt_thread.h" /* Get the thread interface */
  30. #define LDAP_THREAD_IMPLEMENTATION
  31. #define LDAP_THREAD_RDWR_IMPLEMENTATION
  32. #include "ldap_thr_debug.h" /* May rename the symbols defined below */
  33. #include <signal.h> /* For pthread_kill() */
  34. extern int ldap_int_stackguard;
  35. #if HAVE_PTHREADS < 6
  36. # define LDAP_INT_THREAD_ATTR_DEFAULT pthread_attr_default
  37. # define LDAP_INT_THREAD_CONDATTR_DEFAULT pthread_condattr_default
  38. # define LDAP_INT_THREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default
  39. #else
  40. # define LDAP_INT_THREAD_ATTR_DEFAULT NULL
  41. # define LDAP_INT_THREAD_CONDATTR_DEFAULT NULL
  42. # define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL
  43. #endif
  44. #ifdef LDAP_THREAD_DEBUG
  45. # if defined LDAP_INT_THREAD_MUTEXATTR /* May be defined in CPPFLAGS */
  46. # elif defined HAVE_PTHREAD_KILL_OTHER_THREADS_NP
  47. /* LinuxThreads hack */
  48. # define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK_NP
  49. # else
  50. # define LDAP_INT_THREAD_MUTEXATTR PTHREAD_MUTEX_ERRORCHECK
  51. # endif
  52. static pthread_mutexattr_t mutex_attr;
  53. # undef LDAP_INT_THREAD_MUTEXATTR_DEFAULT
  54. # define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr
  55. #endif
  56. static pthread_mutexattr_t mutex_attr_recursive;
  57. #if HAVE_PTHREADS < 7
  58. #define ERRVAL(val) ((val) < 0 ? errno : 0)
  59. #else
  60. #define ERRVAL(val) (val)
  61. #endif
  62. int
  63. ldap_int_thread_initialize( void )
  64. {
  65. #ifdef LDAP_INT_THREAD_MUTEXATTR
  66. pthread_mutexattr_init( &mutex_attr );
  67. pthread_mutexattr_settype( &mutex_attr, LDAP_INT_THREAD_MUTEXATTR );
  68. #endif
  69. if (pthread_mutexattr_init(&mutex_attr_recursive))
  70. return -1;
  71. if (pthread_mutexattr_settype(&mutex_attr_recursive, PTHREAD_MUTEX_RECURSIVE))
  72. return -1;
  73. return 0;
  74. }
  75. int
  76. ldap_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. pthread_mutexattr_destroy( &mutex_attr_recursive );
  86. return 0;
  87. }
  88. #ifdef LDAP_THREAD_HAVE_SETCONCURRENCY
  89. int
  90. ldap_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. #ifdef LDAP_THREAD_HAVE_GETCONCURRENCY
  102. int
  103. ldap_pvt_thread_get_concurrency(void)
  104. {
  105. #ifdef HAVE_PTHREAD_GETCONCURRENCY
  106. return pthread_getconcurrency();
  107. #elif defined(HAVE_THR_GETCONCURRENCY)
  108. return thr_getconcurrency();
  109. #else
  110. return 0;
  111. #endif
  112. }
  113. #endif
  114. /* detachstate appeared in Draft 6, but without manifest constants.
  115. * in Draft 7 they were called PTHREAD_CREATE_UNDETACHED and ...DETACHED.
  116. * in Draft 8 on, ...UNDETACHED became ...JOINABLE.
  117. */
  118. #ifndef PTHREAD_CREATE_JOINABLE
  119. #ifdef PTHREAD_CREATE_UNDETACHED
  120. #define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
  121. #else
  122. #define PTHREAD_CREATE_JOINABLE 0
  123. #endif
  124. #endif
  125. #ifndef PTHREAD_CREATE_DETACHED
  126. #define PTHREAD_CREATE_DETACHED 1
  127. #endif
  128. int
  129. ldap_pvt_thread_create( ldap_pvt_thread_t * thread,
  130. int detach,
  131. void *(*start_routine)( void * ),
  132. void *arg)
  133. {
  134. int rtn;
  135. pthread_attr_t attr;
  136. /* Always create the thread attrs, so we can set stacksize if we need to */
  137. #if HAVE_PTHREADS > 5
  138. pthread_attr_init(&attr);
  139. #else
  140. pthread_attr_create(&attr);
  141. #endif
  142. #ifdef LDAP_PVT_THREAD_SET_STACK_SIZE
  143. /* this should be tunable */
  144. pthread_attr_setstacksize( &attr, LDAP_PVT_THREAD_STACK_SIZE );
  145. if ( ldap_int_stackguard )
  146. pthread_attr_setguardsize( &attr, LDAP_PVT_THREAD_STACK_SIZE );
  147. #endif
  148. #if HAVE_PTHREADS > 5
  149. detach = detach ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE;
  150. #if HAVE_PTHREADS == 6
  151. pthread_attr_setdetachstate(&attr, &detach);
  152. #else
  153. pthread_attr_setdetachstate(&attr, detach);
  154. #endif
  155. #endif
  156. #if HAVE_PTHREADS < 5
  157. rtn = pthread_create( thread, attr, start_routine, arg );
  158. #else
  159. rtn = pthread_create( thread, &attr, start_routine, arg );
  160. #endif
  161. #if HAVE_PTHREADS > 5
  162. pthread_attr_destroy(&attr);
  163. #else
  164. pthread_attr_delete(&attr);
  165. if( detach ) {
  166. pthread_detach( thread );
  167. }
  168. #endif
  169. #if HAVE_PTHREADS < 7
  170. if ( rtn < 0 ) rtn = errno;
  171. #endif
  172. return rtn;
  173. }
  174. void
  175. ldap_pvt_thread_exit( void *retval )
  176. {
  177. pthread_exit( retval );
  178. }
  179. int
  180. ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
  181. {
  182. #if HAVE_PTHREADS < 7
  183. void *dummy;
  184. if (thread_return==NULL)
  185. thread_return=&dummy;
  186. #endif
  187. return ERRVAL( pthread_join( thread, thread_return ) );
  188. }
  189. int
  190. ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
  191. {
  192. #if defined(HAVE_PTHREAD_KILL) && HAVE_PTHREADS > 4
  193. /* MacOS 10.1 is detected as v10 but has no pthread_kill() */
  194. return ERRVAL( pthread_kill( thread, signo ) );
  195. #else
  196. /* pthread package with DCE */
  197. if (kill( getpid(), signo )<0)
  198. return errno;
  199. return 0;
  200. #endif
  201. }
  202. int
  203. ldap_pvt_thread_yield( void )
  204. {
  205. #ifdef REPLACE_BROKEN_YIELD
  206. #ifdef HAVE_NANOSLEEP
  207. struct timespec t = { 0, 0 };
  208. nanosleep(&t, NULL);
  209. #else
  210. struct timeval tv = {0,0};
  211. select( 0, NULL, NULL, NULL, &tv );
  212. #endif
  213. return 0;
  214. #elif defined(HAVE_THR_YIELD)
  215. thr_yield();
  216. return 0;
  217. #elif HAVE_PTHREADS == 10
  218. return sched_yield();
  219. #elif defined(_POSIX_THREAD_IS_GNU_PTH)
  220. sched_yield();
  221. return 0;
  222. #elif HAVE_PTHREADS == 6
  223. pthread_yield(NULL);
  224. return 0;
  225. #else
  226. pthread_yield();
  227. return 0;
  228. #endif
  229. }
  230. int
  231. ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
  232. {
  233. return ERRVAL( pthread_cond_init(
  234. cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) );
  235. }
  236. int
  237. ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
  238. {
  239. return ERRVAL( pthread_cond_destroy( cond ) );
  240. }
  241. int
  242. ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
  243. {
  244. return ERRVAL( pthread_cond_signal( cond ) );
  245. }
  246. int
  247. ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
  248. {
  249. return ERRVAL( pthread_cond_broadcast( cond ) );
  250. }
  251. int
  252. ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond,
  253. ldap_pvt_thread_mutex_t *mutex )
  254. {
  255. return ERRVAL( pthread_cond_wait( cond, mutex ) );
  256. }
  257. int
  258. ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
  259. {
  260. return ERRVAL( pthread_mutex_init(
  261. mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ) );
  262. }
  263. int
  264. ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
  265. {
  266. return ERRVAL( pthread_mutex_destroy( mutex ) );
  267. }
  268. int
  269. ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
  270. {
  271. return ERRVAL( pthread_mutex_lock( mutex ) );
  272. }
  273. int
  274. ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
  275. {
  276. return ERRVAL( pthread_mutex_trylock( mutex ) );
  277. }
  278. int
  279. ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
  280. {
  281. return ERRVAL( pthread_mutex_unlock( mutex ) );
  282. }
  283. int
  284. ldap_pvt_thread_mutex_recursive_init( ldap_pvt_thread_mutex_t *mutex )
  285. {
  286. return ERRVAL( pthread_mutex_init( mutex, &mutex_attr_recursive ) );
  287. }
  288. ldap_pvt_thread_t ldap_pvt_thread_self( void )
  289. {
  290. return pthread_self();
  291. }
  292. int
  293. ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
  294. {
  295. return pthread_key_create( key, NULL );
  296. }
  297. int
  298. ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
  299. {
  300. return pthread_key_delete( key );
  301. }
  302. int
  303. ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
  304. {
  305. return pthread_setspecific( key, data );
  306. }
  307. int
  308. ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
  309. {
  310. *data = pthread_getspecific( key );
  311. return 0;
  312. }
  313. #ifdef LDAP_THREAD_HAVE_RDWR
  314. #ifdef HAVE_PTHREAD_RWLOCK_DESTROY
  315. int
  316. ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
  317. {
  318. return ERRVAL( pthread_rwlock_init( rw, NULL ) );
  319. }
  320. int
  321. ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
  322. {
  323. return ERRVAL( pthread_rwlock_destroy( rw ) );
  324. }
  325. int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
  326. {
  327. return ERRVAL( pthread_rwlock_rdlock( rw ) );
  328. }
  329. int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
  330. {
  331. return ERRVAL( pthread_rwlock_tryrdlock( rw ) );
  332. }
  333. int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
  334. {
  335. return ERRVAL( pthread_rwlock_unlock( rw ) );
  336. }
  337. int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
  338. {
  339. return ERRVAL( pthread_rwlock_wrlock( rw ) );
  340. }
  341. int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
  342. {
  343. return ERRVAL( pthread_rwlock_trywrlock( rw ) );
  344. }
  345. int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
  346. {
  347. return ERRVAL( pthread_rwlock_unlock( rw ) );
  348. }
  349. #endif /* HAVE_PTHREAD_RWLOCK_DESTROY */
  350. #endif /* LDAP_THREAD_HAVE_RDWR */
  351. #endif /* HAVE_PTHREADS */