]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/thr_posix.c
Make use of nanosleep/select as a sched_yeild(2) replacement
[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-2006 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 #if REPLACE_SCHED_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_SCHED_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         return thr_yield();
228
229 #elif HAVE_PTHREADS == 10
230         return sched_yield();
231
232 #elif defined(_POSIX_THREAD_IS_GNU_PTH)
233         sched_yield();
234         return 0;
235
236 #elif HAVE_PTHREADS == 6
237         pthread_yield(NULL);
238         return 0;
239 #else
240         pthread_yield();
241         return 0;
242 #endif
243 }
244
245 int 
246 ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
247 {
248 #if HAVE_PTHREADS < 7
249         if ( pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) < 0 )
250                 return errno;
251         return 0;
252 #else
253         return pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT );
254 #endif
255 }
256
257 int 
258 ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
259 {
260 #if HAVE_PTHREADS < 7
261         if ( pthread_cond_destroy( cond ) < 0 ) return errno;
262         return 0;
263 #else
264         return pthread_cond_destroy( cond );
265 #endif
266 }
267         
268 int 
269 ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
270 {
271 #if HAVE_PTHREADS < 7
272         if ( pthread_cond_signal( cond ) < 0 ) return errno;
273         return 0;
274 #else
275         return pthread_cond_signal( cond );
276 #endif
277 }
278
279 int
280 ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
281 {
282 #if HAVE_PTHREADS < 7
283         if ( pthread_cond_broadcast( cond ) < 0 ) return errno;
284         return 0;
285 #else
286         return pthread_cond_broadcast( cond );
287 #endif
288 }
289
290 int 
291 ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, 
292                       ldap_pvt_thread_mutex_t *mutex )
293 {
294 #if HAVE_PTHREADS < 7
295         if ( pthread_cond_wait( cond, mutex ) < 0 ) return errno;
296         return 0;
297 #else
298         return pthread_cond_wait( cond, mutex );
299 #endif
300 }
301
302 int 
303 ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
304 {
305 #if HAVE_PTHREADS < 7
306         if ( pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT )<0)
307                 return errno;
308         return 0;
309 #else
310         return pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT );
311 #endif
312 }
313
314 int 
315 ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
316 {
317 #if HAVE_PTHREADS < 7
318         if ( pthread_mutex_destroy( mutex ) < 0 ) return errno;
319         return 0;
320 #else
321         return pthread_mutex_destroy( mutex );
322 #endif
323 }
324
325 int 
326 ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
327 {
328 #if HAVE_PTHREADS < 7
329         if ( pthread_mutex_lock( mutex ) < 0 ) return errno;
330         return 0;
331 #else
332         return pthread_mutex_lock( mutex );
333 #endif
334 }
335
336 int 
337 ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
338 {
339 #if HAVE_PTHREADS < 7
340         if ( pthread_mutex_trylock( mutex ) < 0 ) return errno;
341         return 0;
342 #else
343         return pthread_mutex_trylock( mutex );
344 #endif
345 }
346
347 int 
348 ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
349 {
350 #if HAVE_PTHREADS < 7
351         if ( pthread_mutex_unlock( mutex ) < 0 ) return errno;
352         return 0;
353 #else
354         return pthread_mutex_unlock( mutex );
355 #endif
356 }
357
358 ldap_pvt_thread_t ldap_pvt_thread_self( void )
359 {
360         return pthread_self();
361 }
362
363 #ifdef LDAP_THREAD_HAVE_RDWR
364 #ifdef HAVE_PTHREAD_RWLOCK_DESTROY
365 int 
366 ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
367 {
368 #if HAVE_PTHREADS < 7
369         if ( pthread_rwlock_init( rw, NULL ) < 0 ) return errno;
370         return 0;
371 #else
372         return pthread_rwlock_init( rw, NULL );
373 #endif
374 }
375
376 int 
377 ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
378 {
379 #if HAVE_PTHREADS < 7
380         if ( pthread_rwlock_destroy( rw ) < 0 ) return errno;
381         return 0;
382 #else
383         return pthread_rwlock_destroy( rw );
384 #endif
385 }
386
387 int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
388 {
389 #if HAVE_PTHREADS < 7
390         if ( pthread_rwlock_rdlock( rw ) < 0 ) return errno;
391         return 0;
392 #else
393         return pthread_rwlock_rdlock( rw );
394 #endif
395 }
396
397 int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
398 {
399 #if HAVE_PTHREADS < 7
400         if ( pthread_rwlock_tryrdlock( rw ) < 0 ) return errno;
401         return 0;
402 #else
403         return pthread_rwlock_tryrdlock( rw );
404 #endif
405 }
406
407 int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
408 {
409 #if HAVE_PTHREADS < 7
410         if ( pthread_rwlock_unlock( rw ) < 0 ) return errno;
411         return 0;
412 #else
413         return pthread_rwlock_unlock( rw );
414 #endif
415 }
416
417 int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
418 {
419 #if HAVE_PTHREADS < 7
420         if ( pthread_rwlock_wrlock( rw ) < 0 ) return errno;
421         return 0;
422 #else
423         return pthread_rwlock_wrlock( rw );
424 #endif
425 }
426
427 int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
428 {
429 #if HAVE_PTHREADS < 7
430         if ( pthread_rwlock_trywrlock( rw ) < 0 ) return errno;
431         return 0;
432 #else
433         return pthread_rwlock_trywrlock( rw );
434 #endif
435 }
436
437 int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
438 {
439 #if HAVE_PTHREADS < 7
440         if ( pthread_rwlock_unlock( rw ) < 0 ) return errno;
441         return 0;
442 #else
443         return pthread_rwlock_unlock( rw );
444 #endif
445 }
446
447 #endif /* HAVE_PTHREAD_RWLOCK_DESTROY */
448 #endif /* LDAP_THREAD_HAVE_RDWR */
449 #endif /* HAVE_PTHREADS */
450