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