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